summaryrefslogtreecommitdiff
path: root/datapath-windows/ovsext/IpHelper.h
blob: f6955a06ef9ffc843b7a855f908e2f037fdda210 (plain)
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_ */