1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
/*
* Copyright (c) 2014 VMware, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __IP_HELPER_H_
#define __IP_HELPER_H_ 1
#include <ntddk.h>
#include <netioapi.h>
#include "Vport.h"
#define OVS_FWD_HASH_TABLE_SIZE ((UINT32)1 << 10)
#define OVS_FWD_HASH_TABLE_MASK (OVS_FWD_HASH_TABLE_SIZE - 1)
#define OVS_ROUTE_HASH_TABLE_SIZE ((UINT32)1 << 8)
#define OVS_ROUTE_HASH_TABLE_MASK (OVS_ROUTE_HASH_TABLE_SIZE - 1)
#define OVS_NEIGH_HASH_TABLE_SIZE ((UINT32)1 << 8)
#define OVS_NEIGH_HASH_TABLE_MASK (OVS_NEIGH_HASH_TABLE_SIZE - 1)
#define OVS_IPNEIGH_TIMEOUT 100000000 // 10 s
/*
* This structure is used to define each adapter instance.
*
* Note:
* Only when the internal IP is configured and virtual
* internal port is connected, the IP helper request can be
* queued.
*
* We only keep internal IP for reference, it will not be used for determining
* SRC IP of the Tunnel.
*
* The lock must not raise the IRQL higher than PASSIVE_LEVEL in order for the
* route manipulation functions, i.e. GetBestRoute, to work.
*/
typedef struct _OVS_IPHELPER_INSTANCE
{
LIST_ENTRY link;
BOOLEAN isIpConfigured;
UINT32 portNo;
GUID netCfgId;
MIB_IF_ROW2 internalRow;
MIB_IPINTERFACE_ROW internalIPRow;
SOCKADDR_INET ipAddress;
ERESOURCE lock;
} OVS_IPHELPER_INSTANCE, *POVS_IPHELPER_INSTANCE;
typedef struct _OVS_IPNEIGH_ENTRY {
UINT8 macAddr[ETH_ADDR_LEN];
UINT16 refCount;
SOCKADDR_INET ipAddr;
UINT32 pad;
UINT64 timeout;
LIST_ENTRY link;
LIST_ENTRY slink;
LIST_ENTRY fwdList;
POVS_IPHELPER_INSTANCE instance;
} OVS_IPNEIGH_ENTRY, *POVS_IPNEIGH_ENTRY;
typedef struct _OVS_IPFORWARD_ENTRY {
IP_ADDRESS_PREFIX prefix;
SOCKADDR_INET nextHop;
UINT16 refCount;
LIST_ENTRY link;
LIST_ENTRY fwdList;
} OVS_IPFORWARD_ENTRY, *POVS_IPFORWARD_ENTRY;
typedef union _OVS_FWD_INFO {
struct {
SOCKADDR_INET dstIphAddr;
SOCKADDR_INET srcIphAddr;
UINT8 dstMacAddr[ETH_ADDR_LEN];
UINT8 srcMacAddr[ETH_ADDR_LEN];
UINT32 srcPortNo;
POVS_VPORT_ENTRY vport;
};
UINT64 value[10];
} OVS_FWD_INFO, *POVS_FWD_INFO;
typedef struct _OVS_FWD_ENTRY {
OVS_FWD_INFO info;
POVS_IPFORWARD_ENTRY ipf;
POVS_IPNEIGH_ENTRY ipn;
LIST_ENTRY link;
LIST_ENTRY ipfLink;
LIST_ENTRY ipnLink;
} OVS_FWD_ENTRY, *POVS_FWD_ENTRY;
enum {
OVS_IP_HELPER_INTERNAL_ADAPTER_UP,
OVS_IP_HELPER_INTERNAL_ADAPTER_DOWN,
OVS_IP_HELPER_FWD_REQUEST,
};
typedef VOID (*OvsIPHelperCallback)(PNET_BUFFER_LIST nbl,
UINT32 inPort,
PVOID tunnelKey,
PVOID cbData1,
PVOID cbData2,
NTSTATUS status,
POVS_FWD_INFO fwdInfo);
typedef struct _OVS_FWD_REQUEST_INFO {
PNET_BUFFER_LIST nbl;
UINT32 inPort;
OvsIPTunnelKey tunnelKey;
OvsIPHelperCallback cb;
PVOID cbData1;
PVOID cbData2;
} OVS_FWD_REQUEST_INFO, *POVS_FWD_REQUEST_INFO;
typedef struct _OVS_INSTANCE_REQUEST_INFO {
GUID netCfgInstanceId;
UINT32 portNo;
} OVS_INSTANCE_REQUEST_INFO, *POVS_INSTANCE_REQUEST_INFO;
typedef struct _OVS_IP_HELPER_REQUEST {
LIST_ENTRY link;
UINT32 command;
union {
OVS_FWD_REQUEST_INFO fwdReq;
OVS_INSTANCE_REQUEST_INFO instanceReq;
};
} OVS_IP_HELPER_REQUEST, *POVS_IP_HELPER_REQUEST;
typedef struct _OVS_IP_HELPER_THREAD_CONTEXT {
KEVENT event;
PVOID threadObject;
UINT32 exit;
} OVS_IP_HELPER_THREAD_CONTEXT, *POVS_IP_HELPER_THREAD_CONTEXT;
NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle);
VOID OvsCleanupIpHelper(VOID);
VOID OvsInternalAdapterUp(UINT32 portNo, GUID *netCfgInstanceId);
VOID OvsInternalAdapterDown(UINT32 portNo, GUID netCfgInstanceId);
NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort,
const PVOID tunnelKey,
OvsIPHelperCallback cb,
PVOID cbData1,
PVOID cbData2);
VOID OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl);
NTSTATUS
OvsLookupIPhFwdInfo(SOCKADDR_INET srcIp, SOCKADDR_INET dstIp,
POVS_FWD_INFO info);
static __inline BOOLEAN
OvsIphAddrEquals(const SOCKADDR_INET *src, const SOCKADDR_INET *dst)
{
BOOLEAN addrEqual = FALSE;
if (!src || !dst) return FALSE;
if (src->si_family == AF_INET &&
dst->si_family == AF_INET) {
addrEqual = (src->Ipv4.sin_addr.s_addr == dst->Ipv4.sin_addr.s_addr);
} else if(src->si_family == AF_INET6 &&
dst->si_family == AF_INET6) {
if (RtlEqualMemory(&src->Ipv6.sin6_addr,
&dst->Ipv6.sin6_addr,
sizeof(src->Ipv6.sin6_addr))) {
addrEqual = TRUE;
}
}
return addrEqual;
}
/* check if the pointers to SOCKADDR_INET is zero*/
static __inline BOOLEAN
OvsIphIsZero(const SOCKADDR_INET *ipAddr)
{
BOOLEAN isZero = FALSE;
UCHAR zeros[16] = { 0 };
if (!ipAddr) return FALSE;
if (ipAddr->si_family == AF_INET ||
ipAddr->si_family == AF_UNSPEC) {
isZero = (ipAddr->Ipv4.sin_addr.s_addr == 0);
} else if(ipAddr->si_family == AF_INET6) {
if (RtlEqualMemory(&ipAddr->Ipv6.sin6_addr.u.Byte,
&zeros,
sizeof(ipAddr->Ipv6.sin6_addr))) {
isZero = TRUE;
}
}
return isZero;
}
/* Copy the content from the pointer to SOCKADDR_INET
* To the pointer to SOCKADDR_INET
*/
static __inline void
OvsCopyIphAddress(SOCKADDR_INET *dstAddr, const SOCKADDR_INET *srcAddr)
{
if (!srcAddr || !dstAddr) return;
dstAddr->si_family = srcAddr->si_family;
if (srcAddr->si_family == AF_INET) {
dstAddr->Ipv4.sin_addr.s_addr = srcAddr->Ipv4.sin_addr.s_addr;
} else if (srcAddr->si_family == AF_INET6) {
RtlCopyMemory(&dstAddr->Ipv6, &srcAddr->Ipv6,
sizeof(srcAddr->Ipv6));
}
return;
}
/* compute the hash value based on SOCKADDR_INET*/
uint32_t
OvsJhashIphHdr(const SOCKADDR_INET *iphAddr);
NTSTATUS
OvsConvertWcharToAnsiStr(WCHAR* wStr, size_t wlen,
CHAR* str, size_t maxStrLen);
#endif /* __IP_HELPER_H_ */
|