Print this page
Restore SVP_R_ROUTE_REQ, and all that goes with it.
Interpret sl3a_uport == 0 in SVP_R_VL3_ACK to indicate the VL3 IP is a next-hop router.

@@ -359,11 +359,11 @@
 
 typedef enum svp_lookup_type {
         SVP_L_UNKNOWN   = 0x0,
         SVP_L_VL2       = 0x1,
         SVP_L_VL3       = 0x2,
-        SVP_L_RVL3      = 0x3
+        SVP_L_ROUTE     = 0x3
 } svp_lookup_type_t;
 
 typedef struct svp_lookup {
         int svl_type;
         union {

@@ -373,15 +373,15 @@
                 } svl_vl2;
                 struct svl_lookup_vl3 {
                         varpd_arp_handle_t      *svl_vah;
                         uint8_t                 *svl_out;
                 } svl_vl3;
-                struct svl_lookup_rvl3 {
+                struct svl_lookup_route {
                         varpd_query_handle_t    *svl_handle;
                         overlay_target_point_t  *svl_point;
                         overlay_target_route_t  *svl_route;
-                } svl_rvl3;
+                } svl_route;
         } svl_u;
         svp_query_t                             svl_query;
 } svp_lookup_t;
 
 static const char *varpd_svp_props[] = {

@@ -388,11 +388,11 @@
         "svp/host",
         "svp/port",
         "svp/underlay_ip",
         "svp/underlay_port",
         "svp/dcid",
-        "svp/router_mac"
+        "svp/router_oui"
 };
 
 static const uint8_t svp_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
 int

@@ -435,12 +435,14 @@
 
 static void
 svp_vl3_lookup_cb(svp_t *svp, svp_status_t status, const uint8_t *vl2mac,
     const struct in6_addr *uip, const uint16_t uport, void *arg)
 {
-        overlay_target_point_t point;
+        /* Initialize address-holders to 0 for comparisons-to-zeroes later. */
+        overlay_target_point_t point = { 0 };
         svp_lookup_t *svl = arg;
+        uint8_t nexthop_mac[6] = { 0, 0, 0, 0, 0, 0 };
 
         assert(svp != NULL);
         assert(svl != NULL);
 
         if (status != SVP_S_OK) {

@@ -449,13 +451,39 @@
                 umem_cache_free(svp_lookup_cache, svl);
                 return;
         }
 
         /* Inject the L2 mapping before the L3 */
+        if (uport != 0 &&
+            bcmp(uip, &point.otp_ip, sizeof (struct in6_addr)) != 0) {
+                /* Normal L3 lookup result... */
         bcopy(uip, &point.otp_ip, sizeof (struct in6_addr));
         point.otp_port = uport;
         libvarpd_inject_varp(svp->svp_hdl, vl2mac, &point);
+        } else {
+                /*
+                 * Oh my, we have a next-hop router IP.
+                 * Set the MAC to the ouid+vid concatenated
+                 * special-router-MAC. Overlay down below will know
+                 * that uport == 0 means the MAC is a special one.
+                 */
+                if (bcmp(svp->svp_router_oui, nexthop_mac, ETHERADDRL) == 0) {
+                        /*
+                         * We don't have a router_oui, so we can't support
+                         * special-router-MAC.  Drop it.
+                         */
+                        libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
+                            VARPD_LOOKUP_DROP);
+                        umem_cache_free(svp_lookup_cache, svl);
+                        return;
+                }
+                bcopy(svp->svp_router_oui, nexthop_mac, 3);
+                nexthop_mac[3] = (svp->svp_vid >> 16) & 0xff;
+                nexthop_mac[4] = (svp->svp_vid >> 8) & 0xff;
+                nexthop_mac[5] = svp->svp_vid & 0xff;
+                vl2mac = nexthop_mac;
+        }
 
         bcopy(vl2mac, svl->svl_u.svl_vl3.svl_out, ETHERADDRL);
         libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
             VARPD_LOOKUP_OK);
         umem_cache_free(svp_lookup_cache, svl);

@@ -492,35 +520,46 @@
 static void
 svp_shootdown_cb(svp_t *svp, const uint8_t *vl2mac, const struct in6_addr *uip,
     const uint16_t uport)
 {
         /*
-         * We should probably do a conditional invlaidation here.
+         * We should probably do a conditional invalidation here.
          */
         libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
 }
 
 static void
-svp_rvl3_lookup_cb(svp_t *svp, svp_status_t status, /* XXX KEBE SAYS MORE */
+svp_route_lookup_cb(svp_t *svp, svp_status_t status, uint32_t dcid,
+    uint32_t vnetid, uint16_t vlan, uint8_t *srcmac, uint8_t *dstmac,
+    uint16_t ul3_port, uint8_t *ul3_addr, uint8_t srcpfx, uint8_t dstpfx,
     void *arg)
 {
         svp_lookup_t *svl = arg;
         overlay_target_point_t *otp;
         overlay_target_route_t *otr;
 
         if (status != SVP_S_OK) {
-                libvarpd_plugin_query_reply(svl->svl_u.svl_rvl3.svl_handle,
+                libvarpd_plugin_query_reply(svl->svl_u.svl_route.svl_handle,
                     VARPD_LOOKUP_DROP);
                 umem_cache_free(svp_lookup_cache, svl);
                 return;
         }
 
-        otp = svl->svl_u.svl_rvl3.svl_point;
-        otr = svl->svl_u.svl_rvl3.svl_route;
-        /* XXX KEBE SAYS FILL ME IN! */
+        otp = svl->svl_u.svl_route.svl_point;
+        bcopy(dstmac, otp->otp_mac, ETHERADDRL);
+        bcopy(ul3_addr, &otp->otp_ip, sizeof (struct in6_addr));
+        otp->otp_port = ul3_port;
 
-        libvarpd_plugin_query_reply(svl->svl_u.svl_rvl3.svl_handle,
+        otr = svl->svl_u.svl_route.svl_route;
+        otr->otr_vnet = vnetid;
+        otr->otr_vlan = vlan;
+        bcopy(srcmac, otr->otr_srcmac, ETHERADDRL);
+        otr->otr_dcid = dcid;
+        otr->otr_src_prefixlen = srcpfx;
+        otr->otr_dst_prefixlen = dstpfx;
+
+        libvarpd_plugin_query_reply(svl->svl_u.svl_route.svl_handle,
             VARPD_LOOKUP_OK);
         umem_cache_free(svp_lookup_cache, svl);
 }
 
 static svp_cb_t svp_defops = {

@@ -527,11 +566,11 @@
         svp_vl2_lookup_cb,
         svp_vl3_lookup_cb,
         svp_vl2_invalidate_cb,
         svp_vl3_inject_cb,
         svp_shootdown_cb,
-        svp_rvl3_lookup_cb,
+        svp_route_lookup_cb,
 };
 
 static boolean_t
 varpd_svp_valid_dest(overlay_plugin_dest_t dest)
 {

@@ -635,12 +674,11 @@
          *
          * Assume kernel's overlay module is caching well, so we are directly
          * going to query (i.e. no caching up here of actual destinations).
          *
          * Our existing remote sever (svp_remote), but with the new message
-         * SVP_R_REMOTE_VL3_REQ.  Our naming of these functions already has
-         * "remote" in it, but we'll use "rvl3" instead of "vl3".
+         * SVP_R_ROUTE_REQ.
          */
 
         /* XXX KEBE SAYS DO SOME otl verification too... */
         if (IN6_IS_ADDR_V4MAPPED(src)) {
                 if (!IN6_IS_ADDR_V4MAPPED(dst)) {

@@ -660,17 +698,16 @@
         if (slp == NULL) {
                 libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
                 return;
         }
 
-        slp->svl_type = SVP_L_RVL3;
-        slp->svl_u.svl_rvl3.svl_handle = vqh;
-        slp->svl_u.svl_rvl3.svl_point = otp;
-        slp->svl_u.svl_rvl3.svl_route = otr;
+        slp->svl_type = SVP_L_ROUTE;
+        slp->svl_u.svl_route.svl_handle = vqh;
+        slp->svl_u.svl_route.svl_point = otp;
+        slp->svl_u.svl_route.svl_route = otr;
 
-        /* XXX KEBE SAYS FILL IN ARGS PROPERLY... */
-        svp_remote_rvl3_lookup(svp, &slp->svl_query, src, dst, type,
+        svp_remote_route_lookup(svp, &slp->svl_query, src, dst,
             otl->otl_vnetid, (uint16_t)otl->otl_vlan, slp);
 }
 
 static void
 varpd_svp_lookup(void *arg, varpd_query_handle_t *vqh,

@@ -798,11 +835,11 @@
                 libvarpd_prop_set_nodefault(vph);
                 /* XXX KEBE ASKS should I just set high to UINT32_MAX? */
                 libvarpd_prop_set_range_uint32(vph, 1, UINT32_MAX - 1);
                 break;
         case 5:
-                /* svp/router_mac */
+                /* svp/router_oui */
                 libvarpd_prop_set_name(vph, varpd_svp_props[5]);
                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_ETHER);
                 libvarpd_prop_set_nodefault(vph);
                 break;

@@ -909,20 +946,20 @@
 
                 mutex_exit(&svp->svp_lock);
                 return (0);
         }
 
-        /* svp/router_mac */
+        /* svp/router_oui */
         if (strcmp(pname, varpd_svp_props[5]) == 0) {
                 if (*sizep < ETHERADDRL)
                         return (EOVERFLOW);
                 mutex_enter(&svp->svp_lock);
 
-                if (ether_is_zero(&svp->svp_router_mac)) {
+                if (ether_is_zero(&svp->svp_router_oui)) {
                         *sizep = 0;
                 } else {
-                        bcopy(&svp->svp_router_mac, buf, ETHERADDRL);
+                        bcopy(&svp->svp_router_oui, buf, ETHERADDRL);
                         *sizep = ETHERADDRL;
                 }
 
                 mutex_exit(&svp->svp_lock);
                 return (0);

@@ -1027,16 +1064,20 @@
                 mutex_exit(&svp->svp_lock);
 
                 return (0);
         }
 
-        /* svp/router_mac */
+        /* svp/router_oui */
         if (strcmp(pname, varpd_svp_props[5]) == 0) {
                 if (size < ETHERADDRL)
                         return (EOVERFLOW);
                 mutex_enter(&svp->svp_lock);
-                bcopy(buf, &svp->svp_router_mac, ETHERADDRL);
+                bcopy(buf, &svp->svp_router_oui, ETHERADDRL);
+                /* Zero-out the low three bytes. */
+                svp->svp_router_oui[3] = 0;
+                svp->svp_router_oui[4] = 0;
+                svp->svp_router_oui[5] = 0;
                 mutex_exit(&svp->svp_lock);
                 return (0);
         }
 
         return (EINVAL);

@@ -1099,16 +1140,17 @@
                         mutex_exit(&svp->svp_lock);
                         return (ret);
                 }
         }
 
-        /* svp/router_mac */
-        if (!ether_is_zero(&svp->svp_router_mac)) {
+        /* svp/router_oui */
+        if (!ether_is_zero(&svp->svp_router_oui)) {
                 char buf[ETHERADDRSTRL];
 
                 /* XXX KEBE SAYS See underlay_ip... */
-                if (ether_ntoa_r(&svp->svp_router_mac, buf) == NULL) {
+                if (ether_ntoa_r((struct ether_addr *)&svp->svp_router_oui,
+                    buf) == NULL) {
                         libvarpd_panic("unexpected ether_ntoa_r failure: %d",
                             errno);
                 }
 
                 if ((ret = nvlist_add_string(nvp, varpd_svp_props[5],

@@ -1201,19 +1243,20 @@
                         return (ret);
                 }
                 svp->svp_dcid = 0;
         }
 
-        /* svp/router_mac */
+        /* svp/router_oui */
         if ((ret = nvlist_lookup_string(nvp, varpd_svp_props[5],
             &etherstr)) != 0) {
                 if (ret != ENOENT) {
                         varpd_svp_destroy(svp);
                         return (ret);
                 }
-                bzero(&svp->svp_router_mac, ETHERADDRL);
-        } else if (ether_aton_r(etherstr, &svp->svp_router_mac) == NULL) {
+                bzero(&svp->svp_router_oui, ETHERADDRL);
+        } else if (ether_aton_r(etherstr,
+            (struct ether_addr *)&svp->svp_router_oui) == NULL) {
                 libvarpd_panic("unexpected ether_aton_r failure: %d", errno);
         }
 
         svp->svp_hdl = hdl;
         *outp = svp;