[ovs-dev] [PATCH 1/5] datapath-windows: IPv6 support for IpHelper

Sorin Vinturis svinturis at cloudbasesolutions.com
Tue May 31 22:45:22 UTC 2016


Added IPv6 support to the IpHelper module.

Signed-off-by: Sorin Vinturis <svinturis at cloudbasesolutions.com>
---
 datapath-windows/ovsext/Actions.c    |  32 +--
 datapath-windows/ovsext/DpInternal.h |  12 +-
 datapath-windows/ovsext/Flow.c       |  37 ++--
 datapath-windows/ovsext/Gre.c        |  15 +-
 datapath-windows/ovsext/IpHelper.c   | 382 ++++++++++++++++++-----------------
 datapath-windows/ovsext/IpHelper.h   |  12 +-
 datapath-windows/ovsext/Stt.c        |  16 +-
 datapath-windows/ovsext/User.c       |   6 +-
 datapath-windows/ovsext/Util.h       |  33 +++
 datapath-windows/ovsext/Vxlan.c      |  21 +-
 10 files changed, 323 insertions(+), 243 deletions(-)

diff --git a/datapath-windows/ovsext/Actions.c b/datapath-windows/ovsext/Actions.c
index 4edf7d0..909a84a 100644
--- a/datapath-windows/ovsext/Actions.c
+++ b/datapath-windows/ovsext/Actions.c
@@ -317,12 +317,13 @@ OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx,
             if (!vport ||
                 (vport->ovsType != OVS_VPORT_TYPE_NETDEV &&
                  !OvsIsBridgeInternalVport(vport))) {
-                ovsFwdCtx->tunKey.dst = 0;
+                RtlZeroMemory(&ovsFwdCtx->tunKey.dst,
+                              sizeof(ovsFwdCtx->tunKey.dst));
             }
         }
 
         /* Tunnel the packet only if tunnel context is set. */
-        if (ovsFwdCtx->tunKey.dst != 0) {
+        if (!IsNullIpAddr(&ovsFwdCtx->tunKey.dst)) {
             switch(dstVport->ovsType) {
             case OVS_VPORT_TYPE_GRE:
                 ovsActionStats.txGre++;
@@ -498,7 +499,8 @@ static __inline VOID
 OvsClearTunTxCtx(OvsForwardingContext *ovsFwdCtx)
 {
     ovsFwdCtx->tunnelTxNic = NULL;
-    ovsFwdCtx->tunKey.dst = 0;
+    RtlZeroMemory(&ovsFwdCtx->tunKey.dst,
+                  sizeof(ovsFwdCtx->tunKey.dst));
 }
 
 
@@ -512,7 +514,8 @@ static __inline VOID
 OvsClearTunRxCtx(OvsForwardingContext *ovsFwdCtx)
 {
     ovsFwdCtx->tunnelRxNic = NULL;
-    ovsFwdCtx->tunKey.dst = 0;
+    RtlZeroMemory(&ovsFwdCtx->tunKey.dst,
+                  sizeof(ovsFwdCtx->tunKey.dst));
 }
 
 
@@ -574,6 +577,7 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx)
     OvsFlow *flow = NULL;
     UINT64 hash = 0;
     NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+    BOOLEAN isNullDst = IsNullIpAddr(&ovsFwdCtx->tunKey.dst);
     POVS_VPORT_ENTRY vport =
         OvsFindVportByPortNo(ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo);
     if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) {
@@ -585,11 +589,11 @@ OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx)
     ASSERT(vport->nicState == NdisSwitchNicStateConnected);
 
     /* Assert that in the Rx direction, key is always setup. */
-    ASSERT(ovsFwdCtx->tunnelRxNic == NULL || ovsFwdCtx->tunKey.dst != 0);
+    ASSERT(ovsFwdCtx->tunnelRxNic == NULL || !isNullDst);
     status =
         OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo,
                        &key, &ovsFwdCtx->layers,
-                       ovsFwdCtx->tunKey.dst != 0 ? &ovsFwdCtx->tunKey : NULL);
+                       isNullDst ? NULL : &ovsFwdCtx->tunKey);
     if (status != NDIS_STATUS_SUCCESS) {
         OvsCompleteNBLForwardingCtx(ovsFwdCtx,
                                     L"OVS-Flow extract failed");
@@ -902,11 +906,11 @@ OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx)
     if (ovsFwdCtx->tunnelTxNic != NULL) {
         status = OvsTunnelPortTx(ovsFwdCtx);
         ASSERT(ovsFwdCtx->tunnelTxNic == NULL);
-        ASSERT(ovsFwdCtx->tunKey.dst == 0);
+        ASSERT(IsNullIpAddr(&ovsFwdCtx->tunKey.dst));
     } else if (ovsFwdCtx->tunnelRxNic != NULL) {
         status = OvsTunnelPortRx(ovsFwdCtx);
         ASSERT(ovsFwdCtx->tunnelRxNic == NULL);
-        ASSERT(ovsFwdCtx->tunKey.dst == 0);
+        ASSERT(IsNullIpAddr(&ovsFwdCtx->tunKey.dst));
     }
     ASSERT(ovsFwdCtx->curNbl == NULL);
 
@@ -1245,10 +1249,10 @@ OvsTunnelAttrToIPv4TunnelKey(PNL_ATTR attr,
    PNL_ATTR a;
    INT rem;
 
-   tunKey->attr[0] = 0;
-   tunKey->attr[1] = 0;
-   tunKey->attr[2] = 0;
    ASSERT(NlAttrType(attr) == OVS_KEY_ATTR_TUNNEL);
+   for (UINT32 i = 0; i < sizeof(*tunKey) / sizeof(UINT64); i++) {
+      tunKey->attr[i] = 0;
+   }
 
    NL_ATTR_FOR_EACH_UNSAFE (a, rem, NlAttrData(attr),
                             NlAttrGetSize(attr)) {
@@ -1258,10 +1262,12 @@ OvsTunnelAttrToIPv4TunnelKey(PNL_ATTR attr,
          tunKey->flags |= OVS_TNL_F_KEY;
          break;
       case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
-         tunKey->src = NlAttrGetBe32(a);
+         tunKey->src.Ipv4.sin_addr.s_addr = NlAttrGetBe32(a);
+         tunKey->src.si_family = AF_INET;
          break;
       case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
-         tunKey->dst = NlAttrGetBe32(a);
+         tunKey->dst.Ipv4.sin_addr.s_addr = NlAttrGetBe32(a);
+         tunKey->dst.si_family = AF_INET;
          break;
       case OVS_TUNNEL_KEY_ATTR_TOS:
          tunKey->tos = NlAttrGetU8(a);
diff --git a/datapath-windows/ovsext/DpInternal.h b/datapath-windows/ovsext/DpInternal.h
index 07bc180..526efe6 100644
--- a/datapath-windows/ovsext/DpInternal.h
+++ b/datapath-windows/ovsext/DpInternal.h
@@ -128,12 +128,12 @@ typedef struct L2Key {
 } L2Key; /* Size of 24 byte. */
 
 /* Number of packet attributes required to store OVS tunnel key. */
-#define NUM_PKT_ATTR_REQUIRED 3
+#define NUM_PKT_ATTR_REQUIRED 9
 
 typedef union OvsIPv4TunnelKey {
     struct {
-        ovs_be32 dst;
-        ovs_be32 src;
+        SOCKADDR_INET dst;
+        SOCKADDR_INET src;
         ovs_be64 tunnelId;
         uint16_t flags;
         uint8_t  tos;
@@ -147,7 +147,7 @@ typedef union OvsIPv4TunnelKey {
         };
     };
     uint64_t attr[NUM_PKT_ATTR_REQUIRED];
-} OvsIPv4TunnelKey; /* Size of 24 byte. */
+} OvsIPv4TunnelKey; /* Size of 72 byte. */
 
 typedef struct MplsKey {
     ovs_be32 lse;                /* MPLS topmost label stack entry. */
@@ -155,7 +155,7 @@ typedef struct MplsKey {
 } MplsKey; /* Size of 8 bytes. */
 
 typedef __declspec(align(8)) struct OvsFlowKey {
-    OvsIPv4TunnelKey tunKey;     /* 24 bytes */
+    OvsIPv4TunnelKey tunKey;     /* 72 bytes */
     L2Key l2;                    /* 24 bytes */
     union {
         /* These headers are mutually exclusive. */
@@ -254,7 +254,7 @@ typedef struct OvsFlowPut {
     PNL_ATTR  actions;
 } OvsFlowPut;
 
-#define OVS_MIN_PACKET_SIZE 60
+#define OVS_MIN_PACKET_SIZE 108
 typedef struct _OVS_PACKET_INFO {
     uint32_t totalLen;
     uint32_t userDataLen;
diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c
index c2e0227..c40da8a 100644
--- a/datapath-windows/ovsext/Flow.c
+++ b/datapath-windows/ovsext/Flow.c
@@ -964,7 +964,7 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
         goto done;
     }
 
-    if (flowKey->tunKey.dst) {
+    if (!IsNullIpAddr(&flowKey->tunKey.dst)) {
         rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
                                   tunKeyType);
         if (rc != STATUS_SUCCESS) {
@@ -1006,13 +1006,13 @@ MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
     }
 
     if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
-                         tunKey->dst)) {
+                         tunKey->dst.Ipv4.sin_addr.s_addr)) {
         rc = STATUS_UNSUCCESSFUL;
         goto done;
     }
 
     if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
-                         tunKey->src)) {
+                         tunKey->src.Ipv4.sin_addr.s_addr)) {
         rc = STATUS_UNSUCCESSFUL;
         goto done;
     }
@@ -1653,13 +1653,15 @@ MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
         }
 
         if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) {
-        destKey->tunKey.dst = NlAttrGetU32
-                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
+        destKey->tunKey.dst.si_family = AF_INET;
+        destKey->tunKey.dst.Ipv4.sin_addr.s_addr =
+            NlAttrGetU32(tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]);
         }
 
         if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) {
-        destKey->tunKey.src = NlAttrGetU32
-                              (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
+        destKey->tunKey.src.si_family = AF_INET;
+        destKey->tunKey.src.Ipv4.sin_addr.s_addr =
+            NlAttrGetU32(tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]);
         }
 
         if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) {
@@ -1683,9 +1685,9 @@ MapTunAttrToFlowPut(PNL_ATTR *keyAttrs,
         destKey->tunKey.pad = 0;
         destKey->l2.offset = 0;
     } else {
-        destKey->tunKey.attr[0] = 0;
-        destKey->tunKey.attr[1] = 0;
-        destKey->tunKey.attr[2] = 0;
+        for (UINT32 i = 0; i < sizeof(destKey->tunKey) / sizeof(UINT64); i++) {
+            destKey->tunKey.attr[i] = 0;
+        }
         destKey->l2.offset = sizeof destKey->tunKey;
     }
 }
@@ -1887,11 +1889,12 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet,
     layers->value = 0;
 
     if (tunKey) {
-        ASSERT(tunKey->dst != 0);
+        ASSERT(!IsNullIpAddr(&tunKey->dst));
         RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey);
         flow->l2.offset = 0;
     } else {
-        flow->tunKey.dst = 0;
+        RtlZeroMemory(&flow->tunKey.dst,
+                      sizeof(flow->tunKey.dst));
         flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE;
     }
 
@@ -2220,9 +2223,10 @@ OvsLookupFlow(OVS_DATAPATH *datapath,
     UINT16 offset = key->l2.offset;
     UINT16 size = key->l2.keyLen;
     UINT8 *start;
+    BOOLEAN isNullDst = IsNullIpAddr(&key->tunKey.dst);
 
-    ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
-    ASSERT(!key->tunKey.dst || offset == 0);
+    ASSERT(!isNullDst || offset == sizeof(OvsIPv4TunnelKey));
+    ASSERT(isNullDst || offset == 0);
 
     start = (UINT8 *)key + offset;
 
@@ -2277,9 +2281,10 @@ OvsHashFlow(const OvsFlowKey *key)
     UINT16 offset = key->l2.offset;
     UINT16 size = key->l2.keyLen;
     UINT8 *start;
+    BOOLEAN isNullDst = IsNullIpAddr(&key->tunKey.dst);
 
-    ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey));
-    ASSERT(!key->tunKey.dst || offset == 0);
+    ASSERT(!isNullDst || offset == sizeof(OvsIPv4TunnelKey));
+    ASSERT(isNullDst || offset == 0);
     start = (UINT8 *)key + offset;
     return OvsJhashBytes(start, size, 0);
 }
diff --git a/datapath-windows/ovsext/Gre.c b/datapath-windows/ovsext/Gre.c
index cb41593..1cc4e69 100644
--- a/datapath-windows/ovsext/Gre.c
+++ b/datapath-windows/ovsext/Gre.c
@@ -236,10 +236,11 @@ OvsDoEncapGre(POVS_VPORT_ENTRY vport,
                           IP_DF_NBO : 0;
         ipHdr->ttl = tunKey->ttl ? tunKey->ttl : 64;
         ipHdr->protocol = IPPROTO_GRE;
-        ASSERT(tunKey->dst == fwdInfo->dstIpAddr);
-        ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0);
-        ipHdr->saddr = fwdInfo->srcIpAddr;
-        ipHdr->daddr = fwdInfo->dstIpAddr;
+        ASSERT(IsEqualIpAddr(&tunKey->dst, &fwdInfo->dstIpAddr));
+        ASSERT(IsEqualIpAddr(&tunKey->src, &fwdInfo->srcIpAddr) ||
+               IsNullIpAddr(&tunKey->src));
+        ipHdr->saddr = fwdInfo->srcIpAddr.Ipv4.sin_addr.s_addr;
+        ipHdr->daddr = fwdInfo->dstIpAddr.Ipv4.sin_addr.s_addr;
 
         ipHdr->check = 0;
         ipHdr->check = IPChecksum((UINT8 *)ipHdr, sizeof *ipHdr, 0);
@@ -336,8 +337,10 @@ OvsDecapGre(POVS_SWITCH_CONTEXT switchContext,
     headRoom += sizeof *ethHdr;
 
     ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr);
-    tunKey->src = ipHdr->saddr;
-    tunKey->dst = ipHdr->daddr;
+    tunKey->src.Ipv4.sin_addr.s_addr = ipHdr->saddr;
+    tunKey->src.Ipv4.sin_family = AF_INET;
+    tunKey->dst.Ipv4.sin_addr.s_addr = ipHdr->daddr;
+    tunKey->dst.Ipv4.sin_family = AF_INET;
     tunKey->tos = ipHdr->tos;
     tunKey->ttl = ipHdr->ttl;
     tunKey->pad = 0;
diff --git a/datapath-windows/ovsext/IpHelper.c b/datapath-windows/ovsext/IpHelper.c
index d747e8c..b919084 100644
--- a/datapath-windows/ovsext/IpHelper.c
+++ b/datapath-windows/ovsext/IpHelper.c
@@ -46,7 +46,7 @@ static MIB_IPINTERFACE_ROW ovsInternalIPRow;
 /* we only keep one internal IP for reference, it will not be used for
  * determining SRC IP of Tunnel
  */
-static UINT32               ovsInternalIP;
+static SOCKADDR_INET       ovsInternalIP;
 
 
 /*
@@ -81,11 +81,53 @@ static OVS_IP_HELPER_THREAD_CONTEXT ovsIpHelperThreadContext;
 
 static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix);
 static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf);
-static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr);
+static VOID OvsRemoveAllFwdEntriesWithSrc(SOCKADDR_INET ipAddr);
 static VOID OvsCleanupIpHelperRequestList(VOID);
 static VOID OvsCleanupFwdTable(VOID);
 static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn);
 
+static __inline VOID
+OvsDumpIpAddrMsg(CHAR *msg,
+                 const SOCKADDR_INET *ipAddress)
+{
+    if (ipAddress->si_family == AF_INET) {
+        UINT32 ipv4Addr = ipAddress->Ipv4.sin_addr.s_addr;
+        OVS_LOG_INFO("%s: %d.%d.%d.%d", msg,
+                     ipv4Addr & 0xff, (ipv4Addr >> 8) & 0xff,
+                     (ipv4Addr >> 16) & 0xff, (ipv4Addr >> 24) & 0xff);
+    } else {
+        const UCHAR* ipv6Addr = ipAddress->Ipv6.sin6_addr.u.Byte;
+        OVS_LOG_INFO("%s: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+                     ":%02x%02x:%02x%02x", msg,
+                     ipv6Addr[0], ipv6Addr[1], ipv6Addr[2], ipv6Addr[3],
+                     ipv6Addr[4], ipv6Addr[5], ipv6Addr[6], ipv6Addr[7],
+                     ipv6Addr[8], ipv6Addr[9], ipv6Addr[10], ipv6Addr[11],
+                     ipv6Addr[12], ipv6Addr[13], ipv6Addr[14], ipv6Addr[15]);
+    }
+}
+
+static __inline VOID
+OvsDumpIpAddrMsgStatus(CHAR *msg,
+                       const SOCKADDR_INET *ipAddress,
+                       NTSTATUS status)
+{
+    if (ipAddress->si_family == AF_INET) {
+        UINT32 ipv4Addr = ipAddress->Ipv4.sin_addr.s_addr;
+        OVS_LOG_INFO("%s: %d.%d.%d.%d, status: %x", msg,
+                     ipv4Addr & 0xff, (ipv4Addr >> 8) & 0xff,
+                     (ipv4Addr >> 16) & 0xff, (ipv4Addr >> 24) & 0xff, status);
+    } else {
+        const UCHAR* ipv6Addr = ipAddress->Ipv6.sin6_addr.u.Byte;
+        OVS_LOG_INFO("%s: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+                     ":%02x%02x:%02x%02x, status: %x", msg,
+                     ipv6Addr[0], ipv6Addr[1], ipv6Addr[2], ipv6Addr[3],
+                     ipv6Addr[4], ipv6Addr[5], ipv6Addr[6], ipv6Addr[7],
+                     ipv6Addr[8], ipv6Addr[9], ipv6Addr[10], ipv6Addr[11],
+                     ipv6Addr[12], ipv6Addr[13], ipv6Addr[14], ipv6Addr[15],
+                     status);
+    }
+}
+
 static VOID
 OvsDumpIfRow(PMIB_IF_ROW2 ifRow)
 {
@@ -206,20 +248,13 @@ OvsGetIPInterfaceEntry(NET_LUID luid,
 static VOID
 OvsDumpIPEntry(PMIB_UNICASTIPADDRESS_ROW ipRow)
 {
-    UINT32 ipAddr;
-
     OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d",
                  ipRow->InterfaceLuid.Info.NetLuidIndex,
                  ipRow->InterfaceLuid.Info.IfType);
 
     OVS_LOG_INFO("InterfaceIndex: %d", ipRow->InterfaceIndex);
 
-    ASSERT(ipRow->Address.si_family == AF_INET);
-
-    ipAddr = ipRow->Address.Ipv4.sin_addr.s_addr;
-    OVS_LOG_INFO("Unicast Address: %d.%d.%d.%d\n",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, ipAddr >> 24);
+    OvsDumpIpAddrMsg("Unicast Address: ", &ipRow->Address);
 }
 
 
@@ -264,21 +299,9 @@ OvsGetIPEntry(NET_LUID interfaceLuid,
 static VOID
 OvsDumpIPPath(PMIB_IPPATH_ROW ipPath)
 {
-    UINT32 ipAddr = ipPath->Source.Ipv4.sin_addr.s_addr;
-
-    OVS_LOG_INFO("Source: %d.%d.%d.%d",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
-
-    ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr;
-    OVS_LOG_INFO("Destination: %d.%d.%d.%d",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
-
-    ipAddr = ipPath->CurrentNextHop.Ipv4.sin_addr.s_addr;
-    OVS_LOG_INFO("NextHop: %d.%d.%d.%d",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
+    OvsDumpIpAddrMsg("Source: ", &ipPath->Source);
+    OvsDumpIpAddrMsg("Destination: ", &ipPath->Destination);
+    OvsDumpIpAddrMsg("NextHop: ", &ipPath->CurrentNextHop);
 }
 
 
@@ -286,14 +309,11 @@ NTSTATUS
 OvsGetIPPathEntry(PMIB_IPPATH_ROW ipPath)
 {
     NTSTATUS status;
-    UINT32 ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr;
 
     status = GetIpPathEntry(ipPath);
-
     if (status != STATUS_SUCCESS) {
-        OVS_LOG_INFO("Fail to get IP path to %d.%d.%d.%d, status:%x",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
+        OvsDumpIpAddrMsgStatus("Fail to get IP path to: ",
+                               &ipPath->Destination, status);
         return status;
     }
     OvsDumpIPPath(ipPath);
@@ -306,21 +326,9 @@ OvsDumpRoute(const SOCKADDR_INET *sourceAddress,
              const SOCKADDR_INET *destinationAddress,
              PMIB_IPFORWARD_ROW2 route)
 {
-    UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr;
-
-    OVS_LOG_INFO("Destination: %d.%d.%d.%d",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
-
-    ipAddr = sourceAddress->Ipv4.sin_addr.s_addr;
-    OVS_LOG_INFO("Source: %d.%d.%d.%d",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
-
-    ipAddr = route->NextHop.Ipv4.sin_addr.s_addr;
-    OVS_LOG_INFO("NextHop: %d.%d.%d.%d",
-                 ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                 (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
+    OvsDumpIpAddrMsg("Destination: ", destinationAddress);
+    OvsDumpIpAddrMsg("Source: ", sourceAddress);
+    OvsDumpIpAddrMsg("NextHop: ", &route->NextHop);
 }
 
 
@@ -341,10 +349,8 @@ OvsGetRoute(NET_LUID interfaceLuid,
                            0, route, sourceAddress);
 
     if (status != STATUS_SUCCESS) {
-        UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr;
-        OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
+        OvsDumpIpAddrMsgStatus("Fail to get route to: ",
+                               destinationAddress, status);
         return status;
     }
 
@@ -355,11 +361,8 @@ OvsGetRoute(NET_LUID interfaceLuid,
 static VOID
 OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh)
 {
-    UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
+    OvsDumpIpAddrMsg("Neigh: ", &ipNeigh->Address);
 
-    OVS_LOG_INFO("Neigh: %d.%d.%d.%d",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
     OVS_LOG_INFO("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x",
                  ipNeigh->PhysicalAddress[0],
                  ipNeigh->PhysicalAddress[1],
@@ -380,10 +383,8 @@ OvsGetIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
     status = GetIpNetEntry2(ipNeigh);
 
     if (status != STATUS_SUCCESS) {
-        UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
-        OVS_LOG_INFO("Fail to get ARP entry: %d.%d.%d.%d, status: %x",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
+        OvsDumpIpAddrMsgStatus("Fail to get ARP entry: ",
+                               &ipNeigh->Address, status);
         return status;
     }
     if (ipNeigh->State == NlnsReachable ||
@@ -404,10 +405,8 @@ OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
     status = ResolveIpNetEntry2(ipNeigh, NULL);
 
     if (status != STATUS_SUCCESS) {
-        UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
-        OVS_LOG_INFO("Fail to resolve ARP entry: %d.%d.%d.%d, status: %x",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status);
+        OvsDumpIpAddrMsgStatus("Fail to resolve ARP entry: ",
+                               &ipNeigh->Address, status);
         return status;
     }
 
@@ -421,7 +420,7 @@ OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
 
 
 NTSTATUS
-OvsGetOrResolveIPNeigh(UINT32 ipAddr,
+OvsGetOrResolveIPNeigh(SOCKADDR_INET ipAddr,
                        PMIB_IPNET_ROW2 ipNeigh)
 {
     NTSTATUS status;
@@ -431,8 +430,7 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
     RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
     ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
     ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
-    ipNeigh->Address.si_family = AF_INET;
-    ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
+    ipNeigh->Address = ipAddr;
 
     status = OvsGetIPNeighEntry(ipNeigh);
 
@@ -440,8 +438,7 @@ OvsGetOrResolveIPNeigh(UINT32 ipAddr,
         RtlZeroMemory(ipNeigh, sizeof (*ipNeigh));
         ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
         ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex;
-        ipNeigh->Address.si_family = AF_INET;
-        ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr;
+        ipNeigh->Address = ipAddr;
         status = OvsResolveIPNeighEntry(ipNeigh);
     }
     return status;
@@ -514,33 +511,46 @@ OvsChangeCallbackIpRoute(PVOID context,
     UNREFERENCED_PARAMETER(context);
     switch (notificationType) {
     case MibAddInstance:
-
-        ASSERT(ipRoute);
-        ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
-        nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
-
-        OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d added",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
-                     ipRoute->DestinationPrefix.PrefixLength,
-                     nextHop & 0xff, (nextHop >> 8) & 0xff,
-                     (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff);
-        break;
-
-    case MibParameterNotification:
     case MibDeleteInstance:
+    case MibParameterNotification:
         ASSERT(ipRoute);
-        ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
-        nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
-
-        OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
-                     ipRoute->DestinationPrefix.PrefixLength,
-                     nextHop & 0xff, (nextHop >> 8) & 0xff,
-                     (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,
-                     notificationType == MibDeleteInstance ? "deleted" :
-                     "modified");
+
+        if (ipRoute->NextHop.si_family == AF_INET) {
+            ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr;
+            nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
+
+            OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.",
+                         ipAddr & 0xff, (ipAddr >> 8) & 0xff,
+                         (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
+                         ipRoute->DestinationPrefix.PrefixLength,
+                         nextHop & 0xff, (nextHop >> 8) & 0xff,
+                         (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff,
+                         (notificationType == MibAddInstance) ? "added" :
+                         (notificationType == MibDeleteInstance) ? "deleted" :
+                         "modified");
+        } else {
+            UCHAR* ipAddr =
+                ipRoute->DestinationPrefix.Prefix.Ipv6.sin6_addr.u.Byte;
+            UCHAR* nextHop =
+                ipRoute->NextHop.Ipv6.sin6_addr.u.Byte;
+            OVS_LOG_INFO(
+                "IPRoute: To %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\
+                through  %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x %s.",
+                ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], ipAddr[4],
+                ipAddr[5], ipAddr[6], ipAddr[7], ipAddr[8], ipAddr[9],
+                ipAddr[10], ipAddr[11], ipAddr[12], ipAddr[13], ipAddr[14],
+                ipAddr[15], nextHop[0], nextHop[1], nextHop[2], nextHop[3],
+                nextHop[4], nextHop[5], nextHop[6], nextHop[7], nextHop[8],
+                nextHop[9], nextHop[10], nextHop[11], nextHop[12], nextHop[13],
+                nextHop[14], nextHop[15],
+                (notificationType == MibAddInstance) ? "added" :
+                (notificationType == MibDeleteInstance) ? "deleted" :
+                "modified");
+        }
+
+        if (notificationType == MibAddInstance) {
+            break;
+        }
 
         if (ipRoute->InterfaceLuid.Info.NetLuidIndex ==
             ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
@@ -573,33 +583,25 @@ OvsChangeCallbackUnicastIpAddress(PVOID context,
                                   PMIB_UNICASTIPADDRESS_ROW unicastRow,
                                   MIB_NOTIFICATION_TYPE notificationType)
 {
-    UINT32 ipAddr;
-
     UNREFERENCED_PARAMETER(context);
     switch (notificationType) {
     case MibParameterNotification:
     case MibAddInstance:
         ASSERT(unicastRow);
-        ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
         if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
             ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
             unicastRow->InterfaceLuid.Info.IfType ==
             ovsInternalRow.InterfaceLuid.Info.IfType &&
             unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) {
-            ovsInternalIP = ipAddr;
+            ovsInternalIP = unicastRow->Address;
         }
-        OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff,
-                     notificationType == MibAddInstance ? "added": "modified");
+        OvsDumpIpAddrMsg(notificationType == MibAddInstance ?
+                         "IP Address added:" : "IP Address modified:",
+                         &unicastRow->Address);
         break;
 
     case MibDeleteInstance:
         ASSERT(unicastRow);
-        ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr;
-        OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
         if (unicastRow->InterfaceLuid.Info.NetLuidIndex ==
             ovsInternalRow.InterfaceLuid.Info.NetLuidIndex &&
             unicastRow->InterfaceLuid.Info.IfType ==
@@ -608,10 +610,11 @@ OvsChangeCallbackUnicastIpAddress(PVOID context,
 
             LOCK_STATE_EX lockState;
             NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
-            OvsRemoveAllFwdEntriesWithSrc(ipAddr);
+            OvsRemoveAllFwdEntriesWithSrc(unicastRow->Address);
             NdisReleaseRWLock(ovsTableLock, &lockState);
 
         }
+        OvsDumpIpAddrMsg("IP Address removed:", &unicastRow->Address);
         break;
 
     case MibInitialNotification:
@@ -646,28 +649,28 @@ OvsRegisterChangeNotification()
     NTSTATUS status;
 
 
-    status = NotifyIpInterfaceChange(AF_INET, OvsChangeCallbackIpInterface,
+    status = NotifyIpInterfaceChange(AF_UNSPEC, OvsChangeCallbackIpInterface,
                                      NULL, TRUE,
                                      &ipInterfaceNotificationHandle);
     if (status != STATUS_SUCCESS) {
         OVS_LOG_ERROR("Fail to register Notify IP interface change, status:%x.",
-                     status);
+                      status);
         return status;
     }
 
-    status = NotifyRouteChange2(AF_INET, OvsChangeCallbackIpRoute, NULL,
+    status = NotifyRouteChange2(AF_UNSPEC, OvsChangeCallbackIpRoute, NULL,
                                 TRUE, &ipRouteNotificationHandle);
     if (status != STATUS_SUCCESS) {
-        OVS_LOG_ERROR("Fail to regiter ip route change, status: %x.",
-                     status);
+        OVS_LOG_ERROR("Fail to register ip route change, status: %x.",
+                      status);
         goto register_cleanup;
     }
-    status = NotifyUnicastIpAddressChange(AF_INET,
+    status = NotifyUnicastIpAddressChange(AF_UNSPEC,
                                           OvsChangeCallbackUnicastIpAddress,
                                           NULL, TRUE,
                                           &unicastIPNotificationHandle);
     if (status != STATUS_SUCCESS) {
-        OVS_LOG_ERROR("Fail to regiter unicast ip change, status: %x.", status);
+        OVS_LOG_ERROR("Fail to register unicast ip change, status: %x.", status);
     }
 register_cleanup:
     if (status != STATUS_SUCCESS) {
@@ -678,16 +681,54 @@ register_cleanup:
 }
 
 
+static UINT32
+OvsHashIPPrefix(PIP_ADDRESS_PREFIX prefix)
+{
+    UINT32 hash;
+
+    if (prefix->Prefix.si_family == AF_INET) {
+        UINT64 words = (UINT64)prefix->Prefix.Ipv4.sin_addr.s_addr << 32 |
+                       (UINT32)prefix->PrefixLength;
+        hash = OvsJhashWords((UINT32 *)&words, 2, OVS_HASH_BASIS);
+    } else { // prefix->Prefix.si_family == AF_INET6
+        UCHAR words[20] = { 0 };
+        RtlCopyMemory(words, prefix->Prefix.Ipv6.sin6_addr.u.Byte,
+                      sizeof(prefix->Prefix.Ipv6.sin6_addr.u.Byte));
+        *((UINT32*)(&words[16])) = (UINT32)prefix->PrefixLength;
+        hash = OvsJhashBytes((UINT32 *)words, 5, OVS_HASH_BASIS);
+    }
+
+    return hash;
+}
+
+
+static UINT32
+OvsHashIPAddr(SOCKADDR_INET *ipAddr)
+{
+    UINT32 hash;
+
+    if (ipAddr->si_family == AF_INET) {
+        hash = OvsJhashWords((UINT32*)&ipAddr->Ipv4.sin_addr.s_addr,
+                             1, OVS_HASH_BASIS);
+    } else { // ipAddr->si_family == AF_INET6
+        hash = OvsJhashWords((UINT32*)ipAddr->Ipv6.sin6_addr.u.Byte,
+                             4, OVS_HASH_BASIS);
+    }
+
+    return hash;
+}
+
+
 static POVS_IPNEIGH_ENTRY
-OvsLookupIPNeighEntry(UINT32 ipAddr)
+OvsLookupIPNeighEntry(SOCKADDR_INET ipAddr)
 {
     PLIST_ENTRY link;
     POVS_IPNEIGH_ENTRY entry;
-    UINT32 hash = OvsJhashWords(&ipAddr, 1, OVS_HASH_BASIS);
+    UINT32 hash = OvsHashIPAddr(&ipAddr);
 
     LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) {
         entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link);
-        if (entry->ipAddr == ipAddr) {
+        if (IsEqualIpAddr(&entry->ipAddr, &ipAddr)) {
             return entry;
         }
     }
@@ -695,15 +736,6 @@ OvsLookupIPNeighEntry(UINT32 ipAddr)
 }
 
 
-static UINT32
-OvsHashIPPrefix(PIP_ADDRESS_PREFIX prefix)
-{
-    UINT64 words = (UINT64)prefix->Prefix.Ipv4.sin_addr.s_addr << 32 |
-                   (UINT32)prefix->PrefixLength;
-    return OvsJhashWords((UINT32 *)&words, 2, OVS_HASH_BASIS);
-}
-
-
 static POVS_IPFORWARD_ENTRY
 OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
 {
@@ -711,19 +743,12 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
     PLIST_ENTRY link;
     POVS_IPFORWARD_ENTRY ipfEntry;
     UINT32 hash;
-    ASSERT(prefix->Prefix.si_family == AF_INET);
-
-    hash = RtlUlongByteSwap(prefix->Prefix.Ipv4.sin_addr.s_addr);
-
-    ASSERT(prefix->PrefixLength >= 32 ||
-           (hash & (((UINT32)1 <<  (32 - prefix->PrefixLength)) - 1)) == 0);
 
     hash = OvsHashIPPrefix(prefix);
     LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) {
         ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link);
         if (ipfEntry->prefix.PrefixLength == prefix->PrefixLength &&
-            ipfEntry->prefix.Prefix.Ipv4.sin_addr.s_addr ==
-            prefix->Prefix.Ipv4.sin_addr.s_addr) {
+            IsEqualIpAddr(&ipfEntry->prefix.Prefix, &prefix->Prefix)) {
             return ipfEntry;
         }
     }
@@ -732,15 +757,15 @@ OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix)
 
 
 static POVS_FWD_ENTRY
-OvsLookupIPFwdEntry(UINT32 dstIp)
+OvsLookupIPFwdEntry(SOCKADDR_INET dstAddr)
 {
     PLIST_ENTRY link;
     POVS_FWD_ENTRY entry;
-    UINT32 hash = OvsJhashWords(&dstIp, 1, OVS_HASH_BASIS);
+    UINT32 hash = OvsHashIPAddr(&dstAddr);
 
     LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) {
         entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
-        if (entry->info.dstIpAddr == dstIp) {
+        if (IsEqualIpAddr(&entry->info.dstIpAddr, &dstAddr)) {
             return entry;
         }
     }
@@ -749,7 +774,7 @@ OvsLookupIPFwdEntry(UINT32 dstIp)
 
 
 NTSTATUS
-OvsLookupIPFwdInfo(UINT32 dstIp,
+OvsLookupIPFwdInfo(SOCKADDR_INET dstAddr,
                    POVS_FWD_INFO info)
 {
     POVS_FWD_ENTRY entry;
@@ -757,11 +782,11 @@ OvsLookupIPFwdInfo(UINT32 dstIp,
     NTSTATUS status = STATUS_NOT_FOUND;
 
     NdisAcquireRWLockRead(ovsTableLock, &lockState, 0);
-    entry = OvsLookupIPFwdEntry(dstIp);
+    entry = OvsLookupIPFwdEntry(dstAddr);
     if (entry) {
-        info->value[0] = entry->info.value[0];
-        info->value[1] = entry->info.value[1];
-        info->value[2] = entry->info.value[2];
+        for (UINT32 i = 0; i < sizeof(*info) / sizeof(UINT64); i++) {
+            info->value[i] = entry->info.value[i];
+        }
         status = STATUS_SUCCESS;
     }
     NdisReleaseRWLock(ovsTableLock, &lockState);
@@ -772,19 +797,19 @@ OvsLookupIPFwdInfo(UINT32 dstIp,
 static POVS_IPNEIGH_ENTRY
 OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
 {
-
     POVS_IPNEIGH_ENTRY entry;
     UINT64 timeVal;
 
     ASSERT(ipNeigh != NULL);
-    entry = (POVS_IPNEIGH_ENTRY)OvsAllocateMemoryWithTag(
-        sizeof(OVS_IPNEIGH_ENTRY), OVS_IPHELPER_POOL_TAG);
+    entry = (POVS_IPNEIGH_ENTRY)
+        OvsAllocateMemoryWithTag(sizeof(OVS_IPNEIGH_ENTRY),
+                                 OVS_IPHELPER_POOL_TAG);
     if (entry == NULL) {
         return NULL;
     }
 
     RtlZeroMemory(entry, sizeof (OVS_IPNEIGH_ENTRY));
-    entry->ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr;
+    entry->ipAddr = ipNeigh->Address;
     KeQuerySystemTime((LARGE_INTEGER *)&timeVal);
     entry->timeout = timeVal + OVS_IPNEIGH_TIMEOUT;
     RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress,
@@ -798,13 +823,12 @@ OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh)
 static POVS_IPFORWARD_ENTRY
 OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute)
 {
-
     POVS_IPFORWARD_ENTRY entry;
 
     ASSERT(ipRoute);
-
-    entry = (POVS_IPFORWARD_ENTRY)OvsAllocateMemoryWithTag(
-        sizeof(OVS_IPFORWARD_ENTRY), OVS_IPHELPER_POOL_TAG);
+    entry = (POVS_IPFORWARD_ENTRY)
+        OvsAllocateMemoryWithTag(sizeof(OVS_IPFORWARD_ENTRY),
+                                 OVS_IPHELPER_POOL_TAG);
     if (entry == NULL) {
         return NULL;
     }
@@ -812,7 +836,7 @@ OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute)
     RtlZeroMemory(entry, sizeof (OVS_IPFORWARD_ENTRY));
     RtlCopyMemory(&entry->prefix, &ipRoute->DestinationPrefix,
                   sizeof (IP_ADDRESS_PREFIX));
-    entry->nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr;
+    entry->nextHop = ipRoute->NextHop;
     InitializeListHead(&entry->fwdList);
 
     return entry;
@@ -824,14 +848,16 @@ OvsCreateFwdEntry(POVS_FWD_INFO fwdInfo)
 {
     POVS_FWD_ENTRY entry;
 
-    entry = (POVS_FWD_ENTRY)OvsAllocateMemoryWithTag(
-        sizeof(OVS_FWD_ENTRY), OVS_IPHELPER_POOL_TAG);
+    entry = (POVS_FWD_ENTRY)
+        OvsAllocateMemoryWithTag(sizeof(OVS_FWD_ENTRY),
+                                 OVS_IPHELPER_POOL_TAG);
     if (entry == NULL) {
         return NULL;
     }
 
     RtlZeroMemory(entry, sizeof (OVS_FWD_ENTRY));
     RtlCopyMemory(&entry->info, fwdInfo, sizeof (OVS_FWD_INFO));
+
     return entry;
 }
 
@@ -944,7 +970,8 @@ OvsAddIPFwdCache(POVS_FWD_ENTRY fwdEntry,
         NdisAcquireSpinLock(&ovsIpHelperLock);
         OvsAddToSortedNeighList(ipn);
         NdisReleaseSpinLock(&ovsIpHelperLock);
-        hash = OvsJhashWords(&ipn->ipAddr, 1, OVS_HASH_BASIS);
+
+        hash = OvsHashIPAddr(&ipn->ipAddr);
         InsertHeadList(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK],
                        &ipn->link);
     }
@@ -962,7 +989,7 @@ OvsAddIPFwdCache(POVS_FWD_ENTRY fwdEntry,
     ipn->refCount++;
     fwdEntry->ipn = ipn;
 
-    hash = OvsJhashWords(&fwdEntry->info.dstIpAddr, 1, OVS_HASH_BASIS);
+    hash = OvsHashIPAddr(&fwdEntry->info.dstIpAddr);
     InsertHeadList(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK],
                    &fwdEntry->link);
     ovsNumFwdEntries++;
@@ -970,7 +997,7 @@ OvsAddIPFwdCache(POVS_FWD_ENTRY fwdEntry,
 
 
 static VOID
-OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr)
+OvsRemoveAllFwdEntriesWithSrc(SOCKADDR_INET ipAddr)
 {
     UINT32 i;
     POVS_FWD_ENTRY fwdEntry;
@@ -979,7 +1006,7 @@ OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr)
     for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) {
         LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) {
             fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link);
-            if (fwdEntry->info.srcIpAddr == ipAddr) {
+            if (IsEqualIpAddr(&fwdEntry->info.srcIpAddr, &ipAddr)) {
                 OvsRemoveFwdEntry(fwdEntry);
             }
         }
@@ -1109,7 +1136,7 @@ OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
     status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow);
 
     if (status != STATUS_SUCCESS) {
-        OVS_LOG_ERROR("Fali to get IF entry for internal port with GUID"
+        OVS_LOG_ERROR("Fail to get IF entry for internal port with GUID"
                       "  %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
                       netCfgInstanceId->Data1,
                       netCfgInstanceId->Data2,
@@ -1137,7 +1164,7 @@ OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request)
 
     status = OvsGetIPEntry(ovsInternalRow.InterfaceLuid, &ipEntry);
     if (status != STATUS_SUCCESS) {
-        OVS_LOG_INFO("Fali to get IP entry for internal port with GUID"
+        OVS_LOG_INFO("Fail to get IP entry for internal port with GUID"
                      "  %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
                      netCfgInstanceId->Data1,
                      netCfgInstanceId->Data2,
@@ -1208,13 +1235,12 @@ OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl,
 static VOID
 OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
 {
-    SOCKADDR_INET dst, src;
-    NTSTATUS status;
+    NTSTATUS status = STATUS_SUCCESS;
     MIB_IPFORWARD_ROW2 ipRoute;
     MIB_IPNET_ROW2 ipNeigh;
     OVS_FWD_INFO fwdInfo;
-    UINT32 ipAddr;
-    UINT32 srcAddr;
+    SOCKADDR_INET srcAddr;
+    SOCKADDR_INET ipAddr;
     POVS_FWD_ENTRY fwdEntry = NULL;
     POVS_IPFORWARD_ENTRY ipf = NULL;
     POVS_IPNEIGH_ENTRY ipn = NULL;
@@ -1230,33 +1256,31 @@ OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request)
     }
 
     /* find IPRoute */
-    RtlZeroMemory(&dst, sizeof(dst));
-    RtlZeroMemory(&src, sizeof(src));
+    RtlZeroMemory(&srcAddr, sizeof(srcAddr));
     RtlZeroMemory(&ipRoute, sizeof (MIB_IPFORWARD_ROW2));
-    dst.si_family = AF_INET;
-    dst.Ipv4.sin_addr.s_addr = request->fwdReq.tunnelKey.dst;
+    RtlZeroMemory(&ipNeigh, sizeof (ipNeigh));
 
-    status = OvsGetRoute(ovsInternalRow.InterfaceLuid, &dst, &ipRoute, &src);
+    status = OvsGetRoute(ovsInternalRow.InterfaceLuid,
+                         &request->fwdReq.tunnelKey.dst,
+                         &ipRoute, &srcAddr);
     if (status != STATUS_SUCCESS) {
         goto fwd_handle_nbl;
     }
-    srcAddr = src.Ipv4.sin_addr.s_addr;
+    ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
 
     /* find IPNeigh */
-    ipAddr = ipRoute.NextHop.Ipv4.sin_addr.s_addr;
-    if (ipAddr != 0) {
+    ipAddr = ipRoute.NextHop;
+    if (!IsNullIpAddr(&ipAddr)) {
         NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0);
         ipn = OvsLookupIPNeighEntry(ipAddr);
         if (ipn) {
             goto fwd_request_done;
         }
         NdisReleaseRWLock(ovsTableLock, &lockState);
-    }
-    RtlZeroMemory(&ipNeigh, sizeof (ipNeigh));
-    ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value;
-    if (ipAddr == 0) {
+    } else {
         ipAddr = request->fwdReq.tunnelKey.dst;
     }
+
     status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh);
     if (status != STATUS_SUCCESS) {
         goto fwd_handle_nbl;
@@ -1339,10 +1363,8 @@ fwd_handle_nbl:
             ASSERT(ipn && ipn->refCount == 0);
             OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG);
         }
-        ipAddr = request->fwdReq.tunnelKey.dst;
-        OVS_LOG_INFO("Fail to handle IP helper request for dst: %d.%d.%d.%d",
-                     ipAddr & 0xff, (ipAddr >> 8) & 0xff,
-                     (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff);
+        OvsDumpIpAddrMsg("Fail to handle IP helper request for dst: ",
+                         &request->fwdReq.tunnelKey.dst);
     }
     if (request->fwdReq.cb) {
         request->fwdReq.cb(request->fwdReq.nbl,
@@ -1358,7 +1380,7 @@ fwd_handle_nbl:
 
 
 static VOID
-OvsUpdateIPNeighEntry(UINT32 ipAddr,
+OvsUpdateIPNeighEntry(SOCKADDR_INET ipAddr,
                       PMIB_IPNET_ROW2 ipNeigh,
                       NTSTATUS status)
 {
@@ -1425,7 +1447,7 @@ OvsUpdateIPNeighEntry(UINT32 ipAddr,
 
 
 static VOID
-OvsHandleIPNeighTimeout(UINT32 ipAddr)
+OvsHandleIPNeighTimeout(SOCKADDR_INET ipAddr)
 {
     MIB_IPNET_ROW2 ipNeigh;
     NTSTATUS status;
@@ -1488,7 +1510,7 @@ OvsStartIpHelper(PVOID data)
          * IPN
          */
         while (!IsListEmpty(&ovsSortedIPNeighList)) {
-            UINT32 ipAddr;
+            SOCKADDR_INET ipAddr;
             if (context->exit) {
                 goto ip_helper_wait;
             }
@@ -1551,7 +1573,7 @@ OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle)
 
     RtlZeroMemory(&ovsInternalRow, sizeof(MIB_IF_ROW2));
     RtlZeroMemory(&ovsInternalIPRow, sizeof (MIB_IPINTERFACE_ROW));
-    ovsInternalIP = 0;
+    RtlZeroMemory(&ovsInternalIP, sizeof(SOCKADDR_INET));
 
     ovsInternalAdapterUp = FALSE;
 
diff --git a/datapath-windows/ovsext/IpHelper.h b/datapath-windows/ovsext/IpHelper.h
index 8562f86..5a685c3 100644
--- a/datapath-windows/ovsext/IpHelper.h
+++ b/datapath-windows/ovsext/IpHelper.h
@@ -35,7 +35,7 @@
 typedef struct _OVS_IPNEIGH_ENTRY {
     UINT8             macAddr[ETH_ADDR_LEN];
     UINT16            refCount;
-    UINT32            ipAddr;
+    SOCKADDR_INET     ipAddr;
     UINT32            pad;
     UINT64            timeout;
     LIST_ENTRY        link;
@@ -45,7 +45,7 @@ typedef struct _OVS_IPNEIGH_ENTRY {
 
 typedef struct _OVS_IPFORWARD_ENTRY {
     IP_ADDRESS_PREFIX prefix;
-    UINT32            nextHop;
+    SOCKADDR_INET     nextHop;
     UINT16            refCount;
     LIST_ENTRY        link;
     LIST_ENTRY        fwdList;
@@ -53,13 +53,13 @@ typedef struct _OVS_IPFORWARD_ENTRY {
 
 typedef union  _OVS_FWD_INFO {
     struct {
-        UINT32        dstIpAddr;
-        UINT32        srcIpAddr;
+        SOCKADDR_INET dstIpAddr;
+        SOCKADDR_INET srcIpAddr;
         UINT8         dstMacAddr[ETH_ADDR_LEN];
         UINT8         srcMacAddr[ETH_ADDR_LEN];
         UINT32        srcPortNo;
     };
-    UINT64            value[3];
+    UINT64            value[9];
 } OVS_FWD_INFO, *POVS_FWD_INFO;
 
 typedef struct _OVS_FWD_ENTRY {
@@ -122,7 +122,7 @@ NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort,
                                OvsIPHelperCallback cb,
                                PVOID cbData1,
                                PVOID cbData2);
-NTSTATUS OvsLookupIPFwdInfo(UINT32 dstIp, POVS_FWD_INFO info);
+NTSTATUS OvsLookupIPFwdInfo(SOCKADDR_INET dstIp, POVS_FWD_INFO info);
 VOID OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl);
 
 #endif /* __IP_HELPER_H_ */
diff --git a/datapath-windows/ovsext/Stt.c b/datapath-windows/ovsext/Stt.c
index dd7bf92..a7290d5 100644
--- a/datapath-windows/ovsext/Stt.c
+++ b/datapath-windows/ovsext/Stt.c
@@ -270,8 +270,8 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport,
     outerIpHdr->ttl = tunKey->ttl? tunKey->ttl : 64;
     outerIpHdr->protocol = IPPROTO_TCP;
     outerIpHdr->check = 0;
-    outerIpHdr->saddr = fwdInfo->srcIpAddr;
-    outerIpHdr->daddr = tunKey->dst;
+    outerIpHdr->saddr = fwdInfo->srcIpAddr.Ipv4.sin_addr.s_addr;
+    outerIpHdr->daddr = tunKey->dst.Ipv4.sin_addr.s_addr;
 
     /* L4 header */
     RtlZeroMemory(outerTcpHdr, sizeof *outerTcpHdr);
@@ -288,8 +288,10 @@ OvsDoEncapStt(POVS_VPORT_ENTRY vport,
     /* Calculate pseudo header chksum */
     tcpChksumLen = sizeof(TCPHdr) + STT_HDR_LEN + innerFrameLen;
     ASSERT(tcpChksumLen < 65535);
-    outerTcpHdr->check = IPPseudoChecksum(&fwdInfo->srcIpAddr,(uint32 *) &tunKey->dst,
-                                          IPPROTO_TCP, (uint16) tcpChksumLen);
+    outerTcpHdr->check =
+        IPPseudoChecksum((UINT32*)&fwdInfo->srcIpAddr.Ipv4.sin_addr.s_addr,
+                         (UINT32*)&tunKey->dst.Ipv4.sin_addr.s_addr,
+                         IPPROTO_TCP, (uint16) tcpChksumLen);
     sttHdr->version = 0;
 
     /* Set STT Header */
@@ -817,8 +819,10 @@ OvsDecapStt(POVS_SWITCH_CONTEXT switchContext,
     ASSERT(sttHdr);
 
     /* Initialize the tunnel key */
-    tunKey->dst = ipHdr->daddr;
-    tunKey->src = ipHdr->saddr;
+    tunKey->dst.Ipv4.sin_addr.s_addr = ipHdr->daddr;
+    tunKey->dst.si_family = AF_INET;
+    tunKey->src.Ipv4.sin_addr.s_addr = ipHdr->saddr;
+    tunKey->src.si_family = AF_INET;
     tunKey->tunnelId = sttHdr->key;
     tunKey->flags = OVS_TNL_F_KEY;
     tunKey->tos = ipHdr->tos;
diff --git a/datapath-windows/ovsext/User.c b/datapath-windows/ovsext/User.c
index 92a71e1..110a6cc 100644
--- a/datapath-windows/ovsext/User.c
+++ b/datapath-windows/ovsext/User.c
@@ -456,8 +456,10 @@ OvsExecuteDpIoctl(OvsPacketExecute *execute)
         MapTunAttrToFlowPut(execute->keyAttrs, tunnelAttrs, &tempTunKey);
     }
 
-    ndisStatus = OvsExtractFlow(pNbl, execute->inPort, &key, &layers,
-                     tempTunKey.tunKey.dst == 0 ? NULL : &tempTunKey.tunKey);
+    ndisStatus =
+        OvsExtractFlow(pNbl, execute->inPort, &key, &layers,
+                       IsNullIpAddr(&tempTunKey.tunKey.dst) ?
+                       NULL : &tempTunKey.tunKey);
 
     if (ndisStatus == NDIS_STATUS_SUCCESS) {
         NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);
diff --git a/datapath-windows/ovsext/Util.h b/datapath-windows/ovsext/Util.h
index 4bcde3b..3bf457d 100644
--- a/datapath-windows/ovsext/Util.h
+++ b/datapath-windows/ovsext/Util.h
@@ -113,4 +113,37 @@ OvsPerCpuDataInit();
 VOID
 OvsPerCpuDataCleanup();
 
+__inline
+BOOLEAN
+IsNullIpAddr(const SOCKADDR_INET *ipAddr)
+{
+    UCHAR zeros[16] = { 0 };
+
+    if (((ipAddr->si_family == AF_INET || ipAddr->si_family == AF_UNSPEC) &&
+         ipAddr->Ipv4.sin_addr.s_addr == 0) ||
+        (ipAddr->si_family == AF_INET6 &&
+         RtlEqualMemory(&ipAddr->Ipv6.sin6_addr.u.Byte,
+                        &zeros,
+                        sizeof(ipAddr->Ipv6.sin6_addr)))) {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+__inline
+BOOLEAN
+IsEqualIpAddr(const SOCKADDR_INET *src,
+              const SOCKADDR_INET *dst)
+{
+    if ((src->si_family == AF_INET && dst->si_family == AF_INET &&
+         src->Ipv4.sin_addr.s_addr == dst->Ipv4.sin_addr.s_addr) ||
+         (src->si_family == AF_INET6 && dst->si_family == AF_INET6 &&
+         RtlEqualMemory(&src->Ipv6.sin6_addr,
+                        &dst->Ipv6.sin6_addr,
+                        sizeof(src->Ipv6.sin6_addr)))) {
+        return TRUE;
+    }
+    return FALSE;
+}
+
 #endif /* __UTIL_H_ */
diff --git a/datapath-windows/ovsext/Vxlan.c b/datapath-windows/ovsext/Vxlan.c
index 20214cb..63e3680 100644
--- a/datapath-windows/ovsext/Vxlan.c
+++ b/datapath-windows/ovsext/Vxlan.c
@@ -282,10 +282,11 @@ OvsDoEncapVxlan(POVS_VPORT_ENTRY vport,
                           IP_DF_NBO : 0;
         ipHdr->ttl = tunKey->ttl ? tunKey->ttl : VXLAN_DEFAULT_TTL;
         ipHdr->protocol = IPPROTO_UDP;
-        ASSERT(tunKey->dst == fwdInfo->dstIpAddr);
-        ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0);
-        ipHdr->saddr = fwdInfo->srcIpAddr;
-        ipHdr->daddr = fwdInfo->dstIpAddr;
+        ASSERT(IsEqualIpAddr(&tunKey->dst, &fwdInfo->dstIpAddr));
+        ASSERT(IsEqualIpAddr(&tunKey->src, &fwdInfo->srcIpAddr) ||
+               IsNullIpAddr(&tunKey->src));
+        ipHdr->saddr = fwdInfo->srcIpAddr.Ipv4.sin_addr.s_addr;
+        ipHdr->daddr = fwdInfo->dstIpAddr.Ipv4.sin_addr.s_addr;
 
         ipHdr->check = 0;
         ipHdr->check = IPChecksum((UINT8 *)ipHdr, sizeof *ipHdr, 0);
@@ -451,8 +452,10 @@ OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext,
     ethHdr = (EthHdr *)bufferStart;
     /* XXX: Handle IP options. */
     ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr);
-    tunKey->src = ipHdr->saddr;
-    tunKey->dst = ipHdr->daddr;
+    tunKey->src.Ipv4.sin_addr.s_addr = ipHdr->saddr;
+    tunKey->src.Ipv4.sin_family = AF_INET;
+    tunKey->dst.Ipv4.sin_addr.s_addr = ipHdr->daddr;
+    tunKey->dst.Ipv4.sin_family = AF_INET;
     tunKey->tos = ipHdr->tos;
     tunKey->ttl = ipHdr->ttl;
     tunKey->pad = 0;
@@ -530,8 +533,10 @@ OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet,
                                                     &VxlanHeaderBuffer);
 
         if (VxlanHeader) {
-            tunnelKey->src = nh->saddr;
-            tunnelKey->dst = nh->daddr;
+            tunnelKey->src.Ipv4.sin_addr.s_addr = nh->saddr;
+            tunnelKey->src.si_family = AF_INET;
+            tunnelKey->dst.Ipv4.sin_addr.s_addr = nh->daddr;
+            tunnelKey->dst.si_family = AF_INET;
             tunnelKey->ttl = nh->ttl;
             tunnelKey->tos = nh->tos;
             if (VxlanHeader->instanceID) {
-- 
1.9.0.msysgit.0



More information about the dev mailing list