2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
25 #define OVS_DBG_MOD OVS_DBG_IPHELPER
29 * Fow now, we assume only one internal adapter
32 KSTART_ROUTINE OvsStartIpHelper;
36 * Only when the internal IP is configured and virtual
37 * internal port is connected, the IP helper request can be
40 static BOOLEAN ovsInternalIPConfigured;
41 static UINT32 ovsInternalPortNo;
42 static GUID ovsInternalNetCfgId;
43 static MIB_IF_ROW2 ovsInternalRow;
44 static MIB_IPINTERFACE_ROW ovsInternalIPRow;
46 /* we only keep one internal IP for reference, it will not be used for
47 * determining SRC IP of Tunnel
49 static UINT32 ovsInternalIP;
53 * FWD_ENTRY --------> IPFORWARD_ENTRY
55 * |--------------------------------------> IPENIGH_ENTRY
57 * IPFORWARD_ENTRY ------> FWD_ENTRY LIST with same IPFORWARD
59 * IPNEIGH_ENTRY ------> FWD_ENTRY LIST with same IPNEIGH
63 static PLIST_ENTRY ovsFwdHashTable; // based on DST IP
64 static PLIST_ENTRY ovsRouteHashTable; // based on DST PREFIX
65 static PLIST_ENTRY ovsNeighHashTable; // based on DST IP
66 static LIST_ENTRY ovsSortedIPNeighList;
67 static UINT32 ovsNumFwdEntries;
70 static PNDIS_RW_LOCK_EX ovsTableLock;
71 static NDIS_SPIN_LOCK ovsIpHelperLock;
73 static LIST_ENTRY ovsIpHelperRequestList;
74 static UINT32 ovsNumIpHelperRequests;
76 static HANDLE ipInterfaceNotificationHandle;
77 static HANDLE ipRouteNotificationHandle;
78 static HANDLE unicastIPNotificationHandle;
80 static OVS_IP_HELPER_THREAD_CONTEXT ovsIpHelperThreadContext;
82 static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix);
83 static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf);
84 static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr);
85 static VOID OvsCleanupIpHelperRequestList(VOID);
86 static VOID OvsCleanupFwdTable(VOID);
87 static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn);
90 OvsDumpIfRow(PMIB_IF_ROW2 ifRow)
92 OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d",
93 ifRow->InterfaceLuid.Info.NetLuidIndex,
94 ifRow->InterfaceLuid.Info.IfType);
95 OVS_LOG_INFO("InterfaceIndex: %d", ifRow->InterfaceIndex);
97 OVS_LOG_INFO("Interface GUID: %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
98 ifRow->InterfaceGuid.Data1,
99 ifRow->InterfaceGuid.Data2,
100 ifRow->InterfaceGuid.Data3,
101 *(UINT16 *)ifRow->InterfaceGuid.Data4,
102 ifRow->InterfaceGuid.Data4[2],
103 ifRow->InterfaceGuid.Data4[3],
104 ifRow->InterfaceGuid.Data4[4],
105 ifRow->InterfaceGuid.Data4[5],
106 ifRow->InterfaceGuid.Data4[6],
107 ifRow->InterfaceGuid.Data4[7]);
108 OVS_LOG_INFO("Perm MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
109 ifRow->PermanentPhysicalAddress[0],
110 ifRow->PermanentPhysicalAddress[1],
111 ifRow->PermanentPhysicalAddress[2],
112 ifRow->PermanentPhysicalAddress[3],
113 ifRow->PermanentPhysicalAddress[4],
114 ifRow->PermanentPhysicalAddress[5]);
119 OvsDumpIfTable(PMIB_IF_TABLE2 ifTable)
124 OVS_LOG_INFO("======Number of entries: %d========", ifTable->NumEntries);
126 for (i = 0; i < ifTable->NumEntries; i++) {
127 ifRow = &ifTable->Table[i];
134 OvsGetIfEntry(GUID *interfaceGuid, PMIB_IF_ROW2 ifEntry)
137 PMIB_IF_TABLE2 ifTable;
140 if (interfaceGuid == NULL || ifEntry == NULL) {
141 return STATUS_INVALID_PARAMETER;
144 status = GetIfTable2Ex(MibIfTableNormal, &ifTable);
146 if (status != STATUS_SUCCESS) {
147 OVS_LOG_INFO("Fail to get if table, status: %x", status);
150 status = STATUS_NOT_FOUND;
152 for (i = 0; i < ifTable->NumEntries; i++) {
155 ifRow = &ifTable->Table[i];
156 if (!memcmp(interfaceGuid, &ifRow->InterfaceGuid, sizeof (GUID))) {
157 RtlCopyMemory(ifEntry, ifRow, sizeof (MIB_IF_ROW2));
158 status = STATUS_SUCCESS;
159 OvsDumpIfRow(ifEntry);
164 FreeMibTable(ifTable);
170 OvsDumpIPInterfaceEntry(PMIB_IPINTERFACE_ROW ipRow)
172 OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d",
173 ipRow->InterfaceLuid.Info.NetLuidIndex,
174 ipRow->InterfaceLuid.Info.IfType);
175 OVS_LOG_INFO("InterfaceIndex: %d", ipRow->InterfaceIndex);
177 OVS_LOG_INFO("MaxReassembleSize: %u", ipRow->MaxReassemblySize);
182 OvsGetIPInterfaceEntry(NET_LUID luid,
183 PMIB_IPINTERFACE_ROW ipRow)
188 return STATUS_INVALID_PARAMETER;
191 ipRow->Family = AF_INET;
192 ipRow->InterfaceLuid.Value = luid.Value;
194 status = GetIpInterfaceEntry(ipRow);
196 if (status != STATUS_SUCCESS) {
197 OVS_LOG_INFO("Fail to get internal IP Interface mib row, status: %x",
201 OvsDumpIPInterfaceEntry(ipRow);
207 OvsDumpIPEntry(PMIB_UNICASTIPADDRESS_ROW ipRow)
211 OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d",
212 ipRow->InterfaceLuid.Info.NetLuidIndex,
213 ipRow->InterfaceLuid.Info.IfType);
215 OVS_LOG_INFO("InterfaceIndex: %d", ipRow->InterfaceIndex);
217 ASSERT(ipRow->Address.si_family == AF_INET);
219 ipAddr = ipRow->Address.Ipv4.sin_addr.s_addr;
220 OVS_LOG_INFO("Unicast Address: %d.%d.%d.%d\n",
221 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
222 (ipAddr >> 16) & 0xff, ipAddr >> 24);
227 OvsGetIPEntry(NET_LUID interfaceLuid,
228 PMIB_UNICASTIPADDRESS_ROW ipEntry)
230 PMIB_UNICASTIPADDRESS_TABLE ipTable;
234 if (ipEntry == NULL || ipEntry == NULL) {
235 return STATUS_INVALID_PARAMETER;
238 status = GetUnicastIpAddressTable(AF_INET, &ipTable);
240 if (status != STATUS_SUCCESS) {
241 OVS_LOG_INFO("Fail to get unicast address table, status: %x", status);
245 status = STATUS_NOT_FOUND;
247 for (i = 0; i < ipTable->NumEntries; i++) {
248 PMIB_UNICASTIPADDRESS_ROW ipRow;
250 ipRow = &ipTable->Table[i];
251 if (ipRow->InterfaceLuid.Value == interfaceLuid.Value) {
252 RtlCopyMemory(ipEntry, ipRow, sizeof (*ipRow));
253 OvsDumpIPEntry(ipEntry);
254 status = STATUS_SUCCESS;
259 FreeMibTable(ipTable);
263 #ifdef OVS_ENABLE_IPPATH
265 OvsDumpIPPath(PMIB_IPPATH_ROW ipPath)
267 UINT32 ipAddr = ipPath->Source.Ipv4.sin_addr.s_addr;
269 OVS_LOG_INFO("Source: %d.%d.%d.%d",
270 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
271 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
273 ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr;
274 OVS_LOG_INFO("Destination: %d.%d.%d.%d",
275 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
276 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
278 ipAddr = ipPath->CurrentNextHop.Ipv4.sin_addr.s_addr;
279 OVS_LOG_INFO("NextHop: %d.%d.%d.%d",
280 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
281 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
286 OvsGetIPPathEntry(PMIB_IPPATH_ROW ipPath)
289 UINT32 ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr;
291 status = GetIpPathEntry(ipPath);
293 if (status != STATUS_SUCCESS) {
294 OVS_LOG_INFO("Fail to get IP path to %d.%d.%d.%d, status:%x",
295 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
296 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
299 OvsDumpIPPath(ipPath);
305 OvsDumpRoute(const SOCKADDR_INET *sourceAddress,
306 const SOCKADDR_INET *destinationAddress,
307 PMIB_IPFORWARD_ROW2 route)
309 UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr;
311 OVS_LOG_INFO("Destination: %d.%d.%d.%d",
312 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
313 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
315 ipAddr = sourceAddress->Ipv4.sin_addr.s_addr;
316 OVS_LOG_INFO("Source: %d.%d.%d.%d",
317 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
318 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
320 ipAddr = route->NextHop.Ipv4.sin_addr.s_addr;
321 OVS_LOG_INFO("NextHop: %d.%d.%d.%d",
322 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
323 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
328 OvsGetRoute(NET_LUID interfaceLuid,
329 const SOCKADDR_INET *destinationAddress,
330 PMIB_IPFORWARD_ROW2 route,
331 SOCKADDR_INET *sourceAddress)
335 if (destinationAddress == NULL || route == NULL) {
336 return STATUS_INVALID_PARAMETER;
339 status = GetBestRoute2(&interfaceLuid, 0,
340 NULL, destinationAddress,
341 0, route, sourceAddress);
343 if (status != STATUS_SUCCESS) {
344 UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr;
345 OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
346 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
347 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
351 OvsDumpRoute(sourceAddress, destinationAddress, route);
356 OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh)
358 UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
360 OVS_LOG_INFO("Neigh: %d.%d.%d.%d",
361 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
362 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
363 OVS_LOG_INFO("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
364 ipNeigh->PhysicalAddress[0],
365 ipNeigh->PhysicalAddress[1],
366 ipNeigh->PhysicalAddress[2],
367 ipNeigh->PhysicalAddress[3],
368 ipNeigh->PhysicalAddress[4],
369 ipNeigh->PhysicalAddress[5]);
374 OvsGetIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
380 status = GetIpNetEntry2(ipNeigh);
382 if (status != STATUS_SUCCESS) {
383 UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
384 OVS_LOG_INFO("Fail to get ARP entry: %d.%d.%d.%d, status: %x",
385 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
386 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
389 if (ipNeigh->State == NlnsReachable ||
390 ipNeigh->State == NlnsPermanent) {
391 OvsDumpIPNeigh(ipNeigh);
392 return STATUS_SUCCESS;
394 return STATUS_FWP_TCPIP_NOT_READY;
399 OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
404 status = ResolveIpNetEntry2(ipNeigh, NULL);
406 if (status != STATUS_SUCCESS) {
407 UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
408 OVS_LOG_INFO("Fail to resolve ARP entry: %d.%d.%d.%d, status: %x",
409 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
410 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
414 if (ipNeigh->State == NlnsReachable ||
415 ipNeigh->State == NlnsPermanent) {
416 OvsDumpIPNeigh(ipNeigh);
417 return STATUS_SUCCESS;
419 return STATUS_FWP_TCPIP_NOT_READY;
424 OvsGetOrResolveIPNeigh(UINT32 ipAddr,
425 PMIB_IPNET_ROW2 ipNeigh)
431 RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
432 ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
433 ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
434 ipNeigh->Address.si_family = AF_INET;
435 ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
437 status = OvsGetIPNeighEntry(ipNeigh);
439 if (status != STATUS_SUCCESS) {
440 RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
441 ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
442 ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
443 ipNeigh->Address.si_family = AF_INET;
444 ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
445 status = OvsResolveIPNeighEntry(ipNeigh);
452 OvsChangeCallbackIpInterface(PVOID context,
453 PMIB_IPINTERFACE_ROW ipRow,
454 MIB_NOTIFICATION_TYPE notificationType)
456 UNREFERENCED_PARAMETER(context);
457 switch (notificationType) {
458 case MibParameterNotification:
460 if (ipRow->InterfaceLuid.Info.NetLuidIndex ==
461 ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
462 ipRow->InterfaceLuid.Info.IfType ==
463 ovsInternalRow.InterfaceLuid.Info.IfType &&
464 ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
466 * Update the IP Interface Row
468 NdisAcquireSpinLock(&ovsIpHelperLock);
469 RtlCopyMemory(&ovsInternalIPRow, ipRow,
470 sizeof (PMIB_IPINTERFACE_ROW));
471 ovsInternalIPConfigured = TRUE;
472 NdisReleaseSpinLock(&ovsIpHelperLock);
474 OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s",
475 ipRow->InterfaceLuid.Info.NetLuidIndex,
476 ipRow->InterfaceLuid.Info.IfType,
477 notificationType == MibAddInstance ? "added" : "modified");
479 case MibDeleteInstance:
480 OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d, deleted",
481 ipRow->InterfaceLuid.Info.NetLuidIndex,
482 ipRow->InterfaceLuid.Info.IfType);
483 if (ipRow->InterfaceLuid.Info.NetLuidIndex ==
484 ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
485 ipRow->InterfaceLuid.Info.IfType ==
486 ovsInternalRow.InterfaceLuid.Info.IfType &&
487 ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
489 NdisAcquireSpinLock(&ovsIpHelperLock);
490 ovsInternalIPConfigured = FALSE;
491 NdisReleaseSpinLock(&ovsIpHelperLock);
493 OvsCleanupIpHelperRequestList();
495 OvsCleanupFwdTable();
499 case MibInitialNotification:
500 OVS_LOG_INFO("Get Initial notification for IP Interface change.");
508 OvsChangeCallbackIpRoute(PVOID context,
509 PMIB_IPFORWARD_ROW2 ipRoute,
510 MIB_NOTIFICATION_TYPE notificationType)
512 UINT32 ipAddr, nextHop;
514 UNREFERENCED_PARAMETER(context);
515 switch (notificationType) {
519 ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
520 nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
522 OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d added",
523 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
524 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
525 ipRoute->DestinationPrefix.PrefixLength,
526 nextHop & 0xff, (nextHop >> 8) & 0xff,
527 (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff);
530 case MibParameterNotification:
531 case MibDeleteInstance:
533 ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
534 nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
536 OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.",
537 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
538 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
539 ipRoute->DestinationPrefix.PrefixLength,
540 nextHop & 0xff, (nextHop >> 8) & 0xff,
541 (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,
542 notificationType == MibDeleteInstance ? "deleted" :
545 if (ipRoute->InterfaceLuid.Info.NetLuidIndex ==
546 ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
547 ipRoute->InterfaceLuid.Info.IfType ==
548 ovsInternalRow.InterfaceLuid.Info.IfType &&
549 ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
551 POVS_IPFORWARD_ENTRY ipf;
552 LOCK_STATE_EX lockState;
554 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
555 ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix);
557 OvsRemoveIPForwardEntry(ipf);
559 NdisReleaseRWLock(ovsTableLock, &lockState);
563 case MibInitialNotification:
564 OVS_LOG_INFO("Get Initial notification for IP Route change.");
572 OvsChangeCallbackUnicastIpAddress(PVOID context,
573 PMIB_UNICASTIPADDRESS_ROW unicastRow,
574 MIB_NOTIFICATION_TYPE notificationType)
578 UNREFERENCED_PARAMETER(context);
579 switch (notificationType) {
580 case MibParameterNotification:
583 ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
584 if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
585 ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
586 unicastRow->InterfaceLuid.Info.IfType ==
587 ovsInternalRow.InterfaceLuid.Info.IfType &&
588 unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
589 ovsInternalIP = ipAddr;
591 OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s",
592 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
593 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
594 notificationType == MibAddInstance ? "added": "modified");
597 case MibDeleteInstance:
599 ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
600 OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d",
601 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
602 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
603 if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
604 ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
605 unicastRow->InterfaceLuid.Info.IfType ==
606 ovsInternalRow.InterfaceLuid.Info.IfType &&
607 unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
609 LOCK_STATE_EX lockState;
610 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
611 OvsRemoveAllFwdEntriesWithSrc(ipAddr);
612 NdisReleaseRWLock(ovsTableLock, &lockState);
617 case MibInitialNotification:
618 OVS_LOG_INFO("Get Initial notification for Unicast IP Address change.");
626 OvsCancelChangeNotification()
628 if (ipInterfaceNotificationHandle != NULL) {
629 CancelMibChangeNotify2(ipInterfaceNotificationHandle);
630 ipInterfaceNotificationHandle = NULL;
632 if (ipRouteNotificationHandle != NULL) {
633 CancelMibChangeNotify2(ipRouteNotificationHandle);
634 ipRouteNotificationHandle = NULL;
636 if (unicastIPNotificationHandle != NULL) {
637 CancelMibChangeNotify2(unicastIPNotificationHandle);
638 unicastIPNotificationHandle = NULL;
644 OvsRegisterChangeNotification()
649 status = NotifyIpInterfaceChange(AF_INET, OvsChangeCallbackIpInterface,
651 &ipInterfaceNotificationHandle);
652 if (status != STATUS_SUCCESS) {
653 OVS_LOG_ERROR("Fail to register Notify IP interface change, status:%x.",
658 status = NotifyRouteChange2(AF_INET, OvsChangeCallbackIpRoute, NULL,
659 TRUE, &ipRouteNotificationHandle);
660 if (status != STATUS_SUCCESS) {
661 OVS_LOG_ERROR("Fail to regiter ip route change, status: %x.",
663 goto register_cleanup;
665 status = NotifyUnicastIpAddressChange(AF_INET,
666 OvsChangeCallbackUnicastIpAddress,
668 &unicastIPNotificationHandle);
669 if (status != STATUS_SUCCESS) {
670 OVS_LOG_ERROR("Fail to regiter unicast ip change, status: %x.", status);
673 if (status != STATUS_SUCCESS) {
674 OvsCancelChangeNotification();
681 static POVS_IPNEIGH_ENTRY
682 OvsLookupIPNeighEntry(UINT32 ipAddr)
685 POVS_IPNEIGH_ENTRY entry;
686 UINT32 hash = OvsJhashWords(&ipAddr, 1, OVS_HASH_BASIS);
688 LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) {
689 entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link);
690 if (entry->ipAddr == ipAddr) {
699 OvsHashIPPrefix(PIP_ADDRESS_PREFIX prefix)
701 UINT64 words = (UINT64)prefix->Prefix.Ipv4.sin_addr.s_addr << 32 |
702 (UINT32)prefix->PrefixLength;
703 return OvsJhashWords((UINT32 *)&words, 2, OVS_HASH_BASIS);
707 static POVS_IPFORWARD_ENTRY
708 OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
712 POVS_IPFORWARD_ENTRY ipfEntry;
714 ASSERT(prefix->Prefix.si_family == AF_INET);
716 hash = RtlUlongByteSwap(prefix->Prefix.Ipv4.sin_addr.s_addr);
718 ASSERT(prefix->PrefixLength >= 32 ||
719 (hash & (((UINT32)1 << (32 - prefix->PrefixLength)) - 1)) == 0);
721 hash = OvsHashIPPrefix(prefix);
722 LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) {
723 ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link);
724 if (ipfEntry->prefix.PrefixLength == prefix->PrefixLength &&
725 ipfEntry->prefix.Prefix.Ipv4.sin_addr.s_addr ==
726 prefix->Prefix.Ipv4.sin_addr.s_addr) {
734 static POVS_FWD_ENTRY
735 OvsLookupIPFwdEntry(UINT32 dstIp)
738 POVS_FWD_ENTRY entry;
739 UINT32 hash = OvsJhashWords(&dstIp, 1, OVS_HASH_BASIS);
741 LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) {
742 entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
743 if (entry->info.dstIpAddr == dstIp) {
752 OvsLookupIPFwdInfo(UINT32 dstIp,
755 POVS_FWD_ENTRY entry;
756 LOCK_STATE_EX lockState;
757 NTSTATUS status = STATUS_NOT_FOUND;
759 NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);
760 entry = OvsLookupIPFwdEntry(dstIp);
762 info->value[0] = entry->info.value[0];
763 info->value[1] = entry->info.value[1];
764 info->value[2] = entry->info.value[2];
765 status = STATUS_SUCCESS;
767 NdisReleaseRWLock(ovsTableLock, &lockState);
772 static POVS_IPNEIGH_ENTRY
773 OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
776 POVS_IPNEIGH_ENTRY entry;
779 ASSERT(ipNeigh != NULL);
780 entry = (POVS_IPNEIGH_ENTRY)OvsAllocateMemory(sizeof (OVS_IPNEIGH_ENTRY));
785 RtlZeroMemory(entry, sizeof (OVS_IPNEIGH_ENTRY));
786 entry->ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
787 KeQuerySystemTime((LARGE_INTEGER *)&timeVal);
788 entry->timeout = timeVal + OVS_IPNEIGH_TIMEOUT;
789 RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress,
791 InitializeListHead(&entry->fwdList);
797 static POVS_IPFORWARD_ENTRY
798 OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute)
801 POVS_IPFORWARD_ENTRY entry;
806 (POVS_IPFORWARD_ENTRY)OvsAllocateMemory(sizeof (OVS_IPFORWARD_ENTRY));
811 RtlZeroMemory(entry, sizeof (OVS_IPFORWARD_ENTRY));
812 RtlCopyMemory(&entry->prefix, &ipRoute->DestinationPrefix,
813 sizeof (IP_ADDRESS_PREFIX));
814 entry->nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
815 InitializeListHead(&entry->fwdList);
821 static POVS_FWD_ENTRY
822 OvsCreateFwdEntry(POVS_FWD_INFO fwdInfo)
824 POVS_FWD_ENTRY entry;
826 entry = (POVS_FWD_ENTRY)OvsAllocateMemory(sizeof (OVS_FWD_ENTRY));
831 RtlZeroMemory(entry, sizeof (OVS_FWD_ENTRY));
832 RtlCopyMemory(&entry->info, fwdInfo, sizeof (OVS_FWD_INFO));
838 OvsRemoveFwdEntry(POVS_FWD_ENTRY fwdEntry)
840 POVS_IPFORWARD_ENTRY ipf;
841 POVS_IPNEIGH_ENTRY ipn;
846 RemoveEntryList(&fwdEntry->link);
849 RemoveEntryList(&fwdEntry->ipfLink);
852 RemoveEntryList(&fwdEntry->ipnLink);
855 if (ipf->refCount == 0) {
856 ASSERT(IsListEmpty(&ipf->fwdList));
857 RemoveEntryList(&ipf->link);
861 if (ipn->refCount == 0) {
862 ASSERT(IsListEmpty(&ipn->fwdList));
863 RemoveEntryList(&ipn->link);
864 NdisAcquireSpinLock(&ovsIpHelperLock);
865 RemoveEntryList(&ipn->slink);
866 NdisReleaseSpinLock(&ovsIpHelperLock);
870 OvsFreeMemory(fwdEntry);
875 OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf)
877 POVS_FWD_ENTRY fwdEntry;
878 PLIST_ENTRY link, next;
882 LIST_FORALL_SAFE(&ipf->fwdList, link, next) {
883 fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);
884 OvsRemoveFwdEntry(fwdEntry);
886 ASSERT(ipf->refCount == 1);
888 RemoveEntryList(&ipf->link);
894 OvsRemoveIPNeighEntry(POVS_IPNEIGH_ENTRY ipn)
896 PLIST_ENTRY link, next;
897 POVS_FWD_ENTRY fwdEntry;
901 LIST_FORALL_SAFE(&ipn->fwdList, link, next) {
902 fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);
903 OvsRemoveFwdEntry(fwdEntry);
906 if (ipn->refCount == 1) {
907 RemoveEntryList(&ipn->link);
908 NdisAcquireSpinLock(&ovsIpHelperLock);
909 RemoveEntryList(&ipn->slink);
910 NdisReleaseSpinLock(&ovsIpHelperLock);
917 OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn)
920 POVS_IPNEIGH_ENTRY entry;
922 if (!IsListEmpty(&ovsSortedIPNeighList)) {
923 link = ovsSortedIPNeighList.Blink;
924 entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
925 if (entry->timeout > ipn->timeout) {
929 InsertTailList(&ovsSortedIPNeighList, &ipn->slink);
934 OvsAddIPFwdCache(POVS_FWD_ENTRY fwdEntry,
935 POVS_IPFORWARD_ENTRY ipf,
936 POVS_IPNEIGH_ENTRY ipn)
941 if (ipn->refCount == 0) {
942 NdisAcquireSpinLock(&ovsIpHelperLock);
943 OvsAddToSortedNeighList(ipn);
944 NdisReleaseSpinLock(&ovsIpHelperLock);
945 hash = OvsJhashWords(&ipn->ipAddr, 1, OVS_HASH_BASIS);
946 InsertHeadList(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK],
949 if (ipf->refCount == 0) {
950 hash = OvsHashIPPrefix(&ipf->prefix);
951 InsertHeadList(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK],
955 InsertHeadList(&ipf->fwdList, &fwdEntry->ipfLink);
959 InsertHeadList(&ipn->fwdList, &fwdEntry->ipnLink);
963 hash = OvsJhashWords(&fwdEntry->info.dstIpAddr, 1, OVS_HASH_BASIS);
964 InsertHeadList(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK],
971 OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr)
974 POVS_FWD_ENTRY fwdEntry;
975 PLIST_ENTRY link, next;
977 for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
978 LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {
979 fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
980 if (fwdEntry->info.srcIpAddr == ipAddr) {
981 OvsRemoveFwdEntry(fwdEntry);
989 OvsCleanupFwdTable(VOID)
991 PLIST_ENTRY link, next;
992 POVS_IPNEIGH_ENTRY ipn;
994 LOCK_STATE_EX lockState;
996 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
997 if (ovsNumFwdEntries) {
998 LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) {
999 ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
1000 OvsRemoveIPNeighEntry(ipn);
1003 for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
1004 ASSERT(IsListEmpty(&ovsFwdHashTable[i]));
1006 for (i = 0; i < OVS_ROUTE_HASH_TABLE_SIZE; i++) {
1007 ASSERT(IsListEmpty(&ovsRouteHashTable[i]));
1009 NdisReleaseRWLock(ovsTableLock, &lockState);
1014 OvsCleanupIpHelperRequestList(VOID)
1017 PLIST_ENTRY next, link;
1018 POVS_IP_HELPER_REQUEST request;
1020 NdisAcquireSpinLock(&ovsIpHelperLock);
1021 if (ovsNumIpHelperRequests == 0) {
1022 NdisReleaseSpinLock(&ovsIpHelperLock);
1026 InitializeListHead(&list);
1027 OvsAppendList(&list, &ovsIpHelperRequestList);
1028 ovsNumIpHelperRequests = 0;
1029 NdisReleaseSpinLock(&ovsIpHelperLock);
1031 LIST_FORALL_SAFE(&list, link, next) {
1032 request = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
1034 if (request->command == OVS_IP_HELPER_FWD_REQUEST &&
1035 request->fwdReq.cb) {
1036 request->fwdReq.cb(request->fwdReq.nbl,
1037 request->fwdReq.inPort,
1038 &request->fwdReq.tunnelKey,
1039 request->fwdReq.cbData1,
1040 request->fwdReq.cbData2,
1041 STATUS_DEVICE_NOT_READY,
1044 OvsFreeMemory(request);
1051 OvsWakeupIPHelper(VOID)
1053 KeSetEvent(&ovsIpHelperThreadContext.event, 0, FALSE);
1057 OvsInternalAdapterDown(VOID)
1059 NdisAcquireSpinLock(&ovsIpHelperLock);
1060 ovsInternalPortNo = OVS_DEFAULT_PORT_NO;
1061 ovsInternalIPConfigured = FALSE;
1062 NdisReleaseSpinLock(&ovsIpHelperLock);
1064 OvsCleanupIpHelperRequestList();
1066 OvsCleanupFwdTable();
1071 OvsInternalAdapterUp(UINT32 portNo,
1072 GUID *netCfgInstanceId)
1074 POVS_IP_HELPER_REQUEST request;
1076 RtlCopyMemory(&ovsInternalNetCfgId, netCfgInstanceId, sizeof (GUID));
1077 RtlZeroMemory(&ovsInternalRow, sizeof (MIB_IF_ROW2));
1080 (POVS_IP_HELPER_REQUEST)OvsAllocateMemory(sizeof (OVS_IP_HELPER_REQUEST));
1081 if (request == NULL) {
1082 OVS_LOG_ERROR("Fail to initialize Internal Adapter");
1085 RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST));
1086 request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_UP;
1088 NdisAcquireSpinLock(&ovsIpHelperLock);
1089 ovsInternalPortNo = portNo;
1090 InsertHeadList(&ovsIpHelperRequestList, &request->link);
1091 ovsNumIpHelperRequests++;
1092 if (ovsNumIpHelperRequests == 1) {
1093 OvsWakeupIPHelper();
1095 NdisReleaseSpinLock(&ovsIpHelperLock);
1100 OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
1103 MIB_UNICASTIPADDRESS_ROW ipEntry;
1104 GUID *netCfgInstanceId = &ovsInternalNetCfgId;
1106 OvsFreeMemory(request);
1108 status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow);
1110 if (status != STATUS_SUCCESS) {
1111 OVS_LOG_ERROR("Fali to get IF entry for internal port with GUID"
1112 " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
1113 netCfgInstanceId->Data1,
1114 netCfgInstanceId->Data2,
1115 netCfgInstanceId->Data3,
1116 *(UINT16 *)netCfgInstanceId->Data4,
1117 netCfgInstanceId->Data4[2],
1118 netCfgInstanceId->Data4[3],
1119 netCfgInstanceId->Data4[4],
1120 netCfgInstanceId->Data4[5],
1121 netCfgInstanceId->Data4[6],
1122 netCfgInstanceId->Data4[7]);
1126 status = OvsGetIPInterfaceEntry(ovsInternalRow.InterfaceLuid,
1129 if (status == STATUS_SUCCESS) {
1130 NdisAcquireSpinLock(&ovsIpHelperLock);
1131 ovsInternalIPConfigured = TRUE;
1132 NdisReleaseSpinLock(&ovsIpHelperLock);
1137 status = OvsGetIPEntry(ovsInternalRow.InterfaceLuid, &ipEntry);
1138 if (status != STATUS_SUCCESS) {
1139 OVS_LOG_INFO("Fali to get IP entry for internal port with GUID"
1140 " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
1141 netCfgInstanceId->Data1,
1142 netCfgInstanceId->Data2,
1143 netCfgInstanceId->Data3,
1144 *(UINT16 *)netCfgInstanceId->Data4,
1145 netCfgInstanceId->Data4[2],
1146 netCfgInstanceId->Data4[3],
1147 netCfgInstanceId->Data4[4],
1148 netCfgInstanceId->Data4[5],
1149 netCfgInstanceId->Data4[6],
1150 netCfgInstanceId->Data4[7]);
1156 OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request)
1159 NdisAcquireSpinLock(&ovsIpHelperLock);
1161 if (ovsInternalPortNo == OVS_DEFAULT_PORT_NO ||
1162 ovsInternalIPConfigured == FALSE) {
1163 NdisReleaseSpinLock(&ovsIpHelperLock);
1164 OvsFreeMemory(request);
1165 return STATUS_NDIS_ADAPTER_NOT_READY;
1167 InsertHeadList(&ovsIpHelperRequestList, &request->link);
1168 ovsNumIpHelperRequests++;
1169 if (ovsNumIpHelperRequests == 1) {
1170 OvsWakeupIPHelper();
1172 NdisReleaseSpinLock(&ovsIpHelperLock);
1173 return STATUS_SUCCESS;
1179 OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl,
1181 const OvsIPv4TunnelKey *tunnelKey,
1182 OvsIPHelperCallback cb,
1186 POVS_IP_HELPER_REQUEST request;
1189 (POVS_IP_HELPER_REQUEST)OvsAllocateMemory(sizeof (OVS_IP_HELPER_REQUEST));
1191 if (request == NULL) {
1192 return STATUS_INSUFFICIENT_RESOURCES;
1194 request->command = OVS_IP_HELPER_FWD_REQUEST;
1195 request->fwdReq.nbl = nbl;
1196 request->fwdReq.inPort = inPort;
1197 RtlCopyMemory(&request->fwdReq.tunnelKey, tunnelKey,
1198 sizeof (*tunnelKey));
1199 request->fwdReq.cb = cb;
1200 request->fwdReq.cbData1 = cbData1;
1201 request->fwdReq.cbData2 = cbData2;
1203 return OvsEnqueueIpHelperRequest(request);
1208 OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
1210 SOCKADDR_INET dst, src;
1211 NTSTATUS status = STATUS_SUCCESS;
1212 MIB_IPFORWARD_ROW2 ipRoute;
1213 MIB_IPNET_ROW2 ipNeigh;
1214 OVS_FWD_INFO fwdInfo;
1217 POVS_FWD_ENTRY fwdEntry = NULL;
1218 POVS_IPFORWARD_ENTRY ipf = NULL;
1219 POVS_IPNEIGH_ENTRY ipn = NULL;
1220 LOCK_STATE_EX lockState;
1221 BOOLEAN newIPF = FALSE;
1222 BOOLEAN newIPN = FALSE;
1223 BOOLEAN newFWD = FALSE;
1225 status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.dst,
1227 if (status == STATUS_SUCCESS) {
1228 goto fwd_handle_nbl;
1232 RtlZeroMemory(&dst, sizeof(dst));
1233 RtlZeroMemory(&src, sizeof(src));
1234 RtlZeroMemory(&ipRoute, sizeof (MIB_IPFORWARD_ROW2));
1235 dst.si_family = AF_INET;
1236 dst.Ipv4.sin_addr.s_addr = request->fwdReq.tunnelKey.dst;
1238 status = OvsGetRoute(ovsInternalRow.InterfaceLuid, &dst, &ipRoute, &src);
1239 if (status != STATUS_SUCCESS) {
1240 goto fwd_handle_nbl;
1242 srcAddr = src.Ipv4.sin_addr.s_addr;
1245 ipAddr = ipRoute.NextHop.Ipv4.sin_addr.s_addr;
1247 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
1248 ipn = OvsLookupIPNeighEntry(ipAddr);
1250 goto fwd_request_done;
1252 NdisReleaseRWLock(ovsTableLock, &lockState);
1254 RtlZeroMemory(&ipNeigh, sizeof (ipNeigh));
1255 ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
1257 ipAddr = request->fwdReq.tunnelKey.dst;
1259 status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
1260 if (status != STATUS_SUCCESS) {
1261 goto fwd_handle_nbl;
1264 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
1271 ipf = OvsLookupIPForwardEntry(&ipRoute.DestinationPrefix);
1273 ipf = OvsCreateIPForwardEntry(&ipRoute);
1275 NdisReleaseRWLock(ovsTableLock, &lockState);
1276 status = STATUS_INSUFFICIENT_RESOURCES;
1277 goto fwd_handle_nbl;
1282 link = ipf->fwdList.Flink;
1283 fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink);
1284 srcAddr = fwdEntry->info.srcIpAddr;
1291 ipn = OvsLookupIPNeighEntry(ipAddr);
1293 ipn = OvsCreateIPNeighEntry(&ipNeigh);
1295 NdisReleaseRWLock(ovsTableLock, &lockState);
1296 status = STATUS_INSUFFICIENT_RESOURCES;
1297 goto fwd_handle_nbl;
1304 * initialize fwdEntry
1306 fwdInfo.dstIpAddr = request->fwdReq.tunnelKey.dst;
1307 fwdInfo.srcIpAddr = srcAddr;
1308 RtlCopyMemory(fwdInfo.dstMacAddr, ipn->macAddr, MAC_ADDRESS_LEN);
1309 RtlCopyMemory(fwdInfo.srcMacAddr, ovsInternalRow.PhysicalAddress,
1311 fwdInfo.srcPortNo = request->fwdReq.inPort;
1313 fwdEntry = OvsCreateFwdEntry(&fwdInfo);
1314 if (fwdEntry == NULL) {
1315 NdisReleaseRWLock(ovsTableLock, &lockState);
1316 status = STATUS_INSUFFICIENT_RESOURCES;
1317 goto fwd_handle_nbl;
1323 OvsAddIPFwdCache(fwdEntry, ipf, ipn);
1324 NdisReleaseRWLock(ovsTableLock, &lockState);
1328 if (status != STATUS_SUCCESS) {
1330 ASSERT(fwdEntry != NULL);
1331 OvsFreeMemory(fwdEntry);
1334 ASSERT(ipf && ipf->refCount == 0);
1338 ASSERT(ipn && ipn->refCount == 0);
1341 ipAddr = request->fwdReq.tunnelKey.dst;
1342 OVS_LOG_INFO("Fail to handle IP helper request for dst: %d.%d.%d.%d",
1343 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
1344 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
1346 if (request->fwdReq.cb) {
1347 request->fwdReq.cb(request->fwdReq.nbl,
1348 request->fwdReq.inPort,
1349 &request->fwdReq.tunnelKey,
1350 request->fwdReq.cbData1,
1351 request->fwdReq.cbData2,
1353 status == STATUS_SUCCESS ? &fwdInfo : NULL);
1355 OvsFreeMemory(request);
1360 OvsUpdateIPNeighEntry(UINT32 ipAddr,
1361 PMIB_IPNET_ROW2 ipNeigh,
1365 POVS_IPNEIGH_ENTRY ipn;
1366 LOCK_STATE_EX lockState;
1367 KeQuerySystemTime((LARGE_INTEGER *)&timeVal);
1369 * if mac changed, update all relevant fwdEntry
1371 if (status != STATUS_SUCCESS) {
1372 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
1374 NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);
1376 ipn = OvsLookupIPNeighEntry(ipAddr);
1378 NdisReleaseRWLock(ovsTableLock, &lockState);
1381 if (status != STATUS_SUCCESS) {
1382 OvsRemoveIPNeighEntry(ipn);
1383 NdisReleaseRWLock(ovsTableLock, &lockState);
1387 if (memcmp((const PVOID)ipn->macAddr,
1388 (const PVOID)ipNeigh->PhysicalAddress,
1389 (size_t)MAC_ADDRESS_LEN)) {
1391 POVS_FWD_ENTRY fwdEntry;
1392 NdisReleaseRWLock(ovsTableLock, &lockState);
1394 * need update, release and acquire write lock
1395 * This is not the common case.
1398 NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
1399 ipn = OvsLookupIPNeighEntry(ipAddr);
1402 NdisReleaseRWLock(ovsTableLock, &lockState);
1406 LIST_FORALL(&ipn->fwdList, link) {
1407 fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink);
1408 RtlCopyMemory(fwdEntry->info.dstMacAddr,
1409 ipNeigh->PhysicalAddress, MAC_ADDRESS_LEN);
1413 * update timeout and move to the end of
1417 NdisAcquireSpinLock(&ovsIpHelperLock);
1418 RemoveEntryList(&ipn->slink);
1419 ipn->timeout = timeVal + OVS_IPNEIGH_TIMEOUT;
1420 OvsAddToSortedNeighList(ipn);
1421 NdisReleaseSpinLock(&ovsIpHelperLock);
1422 NdisReleaseRWLock(ovsTableLock, &lockState);
1427 OvsHandleIPNeighTimeout(UINT32 ipAddr)
1429 MIB_IPNET_ROW2 ipNeigh;
1432 status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
1434 OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status);
1439 *----------------------------------------------------------------------------
1440 * IP Helper system threash handle following request
1441 * 1. Intialize Internal port row when internal port is connected
1442 * 2. Handle FWD request
1443 * 3. Handle IP Neigh timeout
1445 * IP Interface, unicast address, and IP route change will be handled
1446 * by the revelant callback.
1447 *----------------------------------------------------------------------------
1450 OvsStartIpHelper(PVOID data)
1452 POVS_IP_HELPER_THREAD_CONTEXT context = (POVS_IP_HELPER_THREAD_CONTEXT)data;
1453 POVS_IP_HELPER_REQUEST req;
1454 POVS_IPNEIGH_ENTRY ipn;
1456 UINT64 timeVal, timeout;
1458 OVS_LOG_INFO("Start the IP Helper Thread, context: %p", context);
1460 NdisAcquireSpinLock(&ovsIpHelperLock);
1461 while (!context->exit) {
1464 while (!IsListEmpty(&ovsIpHelperRequestList)) {
1465 if (context->exit) {
1466 goto ip_helper_wait;
1468 link = ovsIpHelperRequestList.Flink;
1469 RemoveEntryList(link);
1470 NdisReleaseSpinLock(&ovsIpHelperLock);
1471 req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
1472 switch (req->command) {
1473 case OVS_IP_HELPER_INTERNAL_ADAPTER_UP:
1474 OvsHandleInternalAdapterUp(req);
1476 case OVS_IP_HELPER_FWD_REQUEST:
1477 OvsHandleFwdRequest(req);
1482 NdisAcquireSpinLock(&ovsIpHelperLock);
1485 /* for now, let us hold the lock here, if this cause any issue
1486 * we will change to use IpHelper lock only to protect
1489 while (!IsListEmpty(&ovsSortedIPNeighList)) {
1491 if (context->exit) {
1492 goto ip_helper_wait;
1494 link = ovsSortedIPNeighList.Flink;
1495 ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink);
1496 KeQuerySystemTime((LARGE_INTEGER *)&timeVal);
1497 if (ipn->timeout > timeVal) {
1498 timeout = ipn->timeout;
1501 ipAddr = ipn->ipAddr;
1503 NdisReleaseSpinLock(&ovsIpHelperLock);
1505 OvsHandleIPNeighTimeout(ipAddr);
1507 NdisAcquireSpinLock(&ovsIpHelperLock);
1509 if (!IsListEmpty(&ovsIpHelperRequestList)) {
1514 if (context->exit) {
1518 KeClearEvent(&context->event);
1519 NdisReleaseSpinLock(&ovsIpHelperLock);
1521 KeWaitForSingleObject(&context->event, Executive, KernelMode,
1522 FALSE, (LARGE_INTEGER *)&timeout);
1523 NdisAcquireSpinLock(&ovsIpHelperLock);
1525 NdisReleaseSpinLock(&ovsIpHelperLock);
1526 OvsCleanupFwdTable();
1527 OvsCleanupIpHelperRequestList();
1529 OVS_LOG_INFO("Terminating the OVS IP Helper system thread");
1531 PsTerminateSystemThread(STATUS_SUCCESS);
1536 OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle)
1539 HANDLE threadHandle;
1542 ovsFwdHashTable = (PLIST_ENTRY)OvsAllocateMemory(sizeof(LIST_ENTRY) *
1543 OVS_FWD_HASH_TABLE_SIZE);
1545 ovsRouteHashTable = (PLIST_ENTRY)OvsAllocateMemory(sizeof(LIST_ENTRY) *
1546 OVS_ROUTE_HASH_TABLE_SIZE);
1548 ovsNeighHashTable = (PLIST_ENTRY)OvsAllocateMemory(sizeof(LIST_ENTRY) *
1549 OVS_NEIGH_HASH_TABLE_SIZE);
1551 RtlZeroMemory(&ovsInternalRow, sizeof(MIB_IF_ROW2));
1552 RtlZeroMemory(&ovsInternalIPRow, sizeof (MIB_IPINTERFACE_ROW));
1555 ovsInternalPortNo = OVS_DEFAULT_PORT_NO;
1557 InitializeListHead(&ovsSortedIPNeighList);
1559 ovsTableLock = NdisAllocateRWLock(ndisFilterHandle);
1560 NdisAllocateSpinLock(&ovsIpHelperLock);
1562 InitializeListHead(&ovsIpHelperRequestList);
1563 ovsNumIpHelperRequests = 0;
1564 ipInterfaceNotificationHandle = NULL;
1565 ipRouteNotificationHandle = NULL;
1566 unicastIPNotificationHandle = NULL;
1568 if (ovsFwdHashTable == NULL ||
1569 ovsRouteHashTable == NULL ||
1570 ovsNeighHashTable == NULL ||
1571 ovsTableLock == NULL) {
1572 status = STATUS_INSUFFICIENT_RESOURCES;
1576 for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
1577 InitializeListHead(&ovsFwdHashTable[i]);
1580 for (i = 0; i < OVS_ROUTE_HASH_TABLE_SIZE; i++) {
1581 InitializeListHead(&ovsRouteHashTable[i]);
1584 for (i = 0; i < OVS_NEIGH_HASH_TABLE_SIZE; i++) {
1585 InitializeListHead(&ovsNeighHashTable[i]);
1589 KeInitializeEvent(&ovsIpHelperThreadContext.event, NotificationEvent,
1591 status = OvsRegisterChangeNotification();
1592 ovsIpHelperThreadContext.exit = 0;
1593 if (status == STATUS_SUCCESS) {
1594 status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE,
1595 NULL, NULL, NULL, OvsStartIpHelper,
1596 &ovsIpHelperThreadContext);
1597 if (status != STATUS_SUCCESS) {
1600 ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL,
1602 &ovsIpHelperThreadContext.threadObject,
1604 ZwClose(threadHandle);
1609 if (status != STATUS_SUCCESS) {
1610 OvsCancelChangeNotification();
1611 if (ovsFwdHashTable) {
1612 OvsFreeMemory(ovsFwdHashTable);
1613 ovsFwdHashTable = NULL;
1615 if (ovsRouteHashTable) {
1616 OvsFreeMemory(ovsRouteHashTable);
1617 ovsRouteHashTable = NULL;
1619 if (ovsNeighHashTable) {
1620 OvsFreeMemory(ovsNeighHashTable);
1621 ovsNeighHashTable = NULL;
1624 NdisFreeRWLock(ovsTableLock);
1625 ovsTableLock = NULL;
1627 NdisFreeSpinLock(&ovsIpHelperLock);
1629 return STATUS_SUCCESS;
1634 OvsCleanupIpHelper(VOID)
1636 OvsCancelChangeNotification();
1638 NdisAcquireSpinLock(&ovsIpHelperLock);
1639 ovsIpHelperThreadContext.exit = 1;
1640 OvsWakeupIPHelper();
1641 NdisReleaseSpinLock(&ovsIpHelperLock);
1643 KeWaitForSingleObject(ovsIpHelperThreadContext.threadObject, Executive,
1644 KernelMode, FALSE, NULL);
1645 ObDereferenceObject(ovsIpHelperThreadContext.threadObject);
1647 OvsFreeMemory(ovsFwdHashTable);
1648 OvsFreeMemory(ovsRouteHashTable);
1649 OvsFreeMemory(ovsNeighHashTable);
1651 NdisFreeRWLock(ovsTableLock);
1652 NdisFreeSpinLock(&ovsIpHelperLock);
1656 OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl)
1658 PLIST_ENTRY link, next;
1659 POVS_IP_HELPER_REQUEST req;
1661 InitializeListHead(&list);
1663 NdisAcquireSpinLock(&ovsIpHelperLock);
1664 LIST_FORALL_SAFE(&ovsIpHelperRequestList, link, next) {
1665 req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
1666 if (req->command == OVS_IP_HELPER_FWD_REQUEST &&
1667 (nbl == NULL || req->fwdReq.nbl == nbl)) {
1668 RemoveEntryList(link);
1669 InsertHeadList(&list, link);
1675 NdisReleaseSpinLock(&ovsIpHelperLock);
1677 LIST_FORALL_SAFE(&list, link, next) {
1678 req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link);
1679 if (req->fwdReq.cb) {
1680 req->fwdReq.cb(req->fwdReq.nbl, req->fwdReq.inPort,
1681 &req->fwdReq.tunnelKey,
1682 req->fwdReq.cbData1,
1683 req->fwdReq.cbData2,
1684 STATUS_DEVICE_NOT_READY,