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.


 344 #include <netinet/in.h>
 345 #include <arpa/inet.h>
 346 #include <libnvpair.h>
 347 #include <strings.h>
 348 #include <string.h>
 349 #include <assert.h>
 350 #include <unistd.h>
 351 
 352 #include <libvarpd_provider.h>
 353 #include "libvarpd_svp.h"
 354 
 355 bunyan_logger_t *svp_bunyan;
 356 static int svp_defport = 1296;
 357 static int svp_defuport = 1339;
 358 static umem_cache_t *svp_lookup_cache;
 359 
 360 typedef enum svp_lookup_type {
 361         SVP_L_UNKNOWN   = 0x0,
 362         SVP_L_VL2       = 0x1,
 363         SVP_L_VL3       = 0x2,
 364         SVP_L_RVL3      = 0x3
 365 } svp_lookup_type_t;
 366 
 367 typedef struct svp_lookup {
 368         int svl_type;
 369         union {
 370                 struct svl_lookup_vl2 {
 371                         varpd_query_handle_t    *svl_handle;
 372                         overlay_target_point_t  *svl_point;
 373                 } svl_vl2;
 374                 struct svl_lookup_vl3 {
 375                         varpd_arp_handle_t      *svl_vah;
 376                         uint8_t                 *svl_out;
 377                 } svl_vl3;
 378                 struct svl_lookup_rvl3 {
 379                         varpd_query_handle_t    *svl_handle;
 380                         overlay_target_point_t  *svl_point;
 381                         overlay_target_route_t  *svl_route;
 382                 } svl_rvl3;
 383         } svl_u;
 384         svp_query_t                             svl_query;
 385 } svp_lookup_t;
 386 
 387 static const char *varpd_svp_props[] = {
 388         "svp/host",
 389         "svp/port",
 390         "svp/underlay_ip",
 391         "svp/underlay_port",
 392         "svp/dcid",
 393         "svp/router_mac"
 394 };
 395 
 396 static const uint8_t svp_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 397 
 398 int
 399 svp_comparator(const void *l, const void *r)
 400 {
 401         const svp_t *ls = l;
 402         const svp_t *rs = r;
 403 
 404         if (ls->svp_vid > rs->svp_vid)
 405                 return (1);
 406         if (ls->svp_vid < rs->svp_vid)
 407                 return (-1);
 408         return (0);
 409 }
 410 
 411 static void
 412 svp_vl2_lookup_cb(svp_t *svp, svp_status_t status, const struct in6_addr *uip,
 413     const uint16_t uport, void *arg)


 420 
 421         if (status != SVP_S_OK) {
 422                 libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
 423                     VARPD_LOOKUP_DROP);
 424                 umem_cache_free(svp_lookup_cache, svl);
 425                 return;
 426         }
 427 
 428         otp = svl->svl_u.svl_vl2.svl_point;
 429         bcopy(uip, &otp->otp_ip, sizeof (struct in6_addr));
 430         otp->otp_port = uport;
 431         libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
 432             VARPD_LOOKUP_OK);
 433         umem_cache_free(svp_lookup_cache, svl);
 434 }
 435 
 436 static void
 437 svp_vl3_lookup_cb(svp_t *svp, svp_status_t status, const uint8_t *vl2mac,
 438     const struct in6_addr *uip, const uint16_t uport, void *arg)
 439 {
 440         overlay_target_point_t point;

 441         svp_lookup_t *svl = arg;

 442 
 443         assert(svp != NULL);
 444         assert(svl != NULL);
 445 
 446         if (status != SVP_S_OK) {
 447                 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
 448                     VARPD_LOOKUP_DROP);
 449                 umem_cache_free(svp_lookup_cache, svl);
 450                 return;
 451         }
 452 
 453         /* Inject the L2 mapping before the L3 */



 454         bcopy(uip, &point.otp_ip, sizeof (struct in6_addr));
 455         point.otp_port = uport;
 456         libvarpd_inject_varp(svp->svp_hdl, vl2mac, &point);























 457 
 458         bcopy(vl2mac, svl->svl_u.svl_vl3.svl_out, ETHERADDRL);
 459         libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
 460             VARPD_LOOKUP_OK);
 461         umem_cache_free(svp_lookup_cache, svl);
 462 }
 463 
 464 static void
 465 svp_vl2_invalidate_cb(svp_t *svp, const uint8_t *vl2mac)
 466 {
 467         libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
 468 }
 469 
 470 static void
 471 svp_vl3_inject_cb(svp_t *svp, const uint16_t vlan, const struct in6_addr *vl3ip,
 472     const uint8_t *vl2mac, const uint8_t *targmac)
 473 {
 474         struct in_addr v4;
 475 
 476         /*
 477          * At the moment we don't support any IPv6 related log entries, this
 478          * will change soon as we develop a bit more of the IPv6 related
 479          * infrastructure so we can properly test the injection.
 480          */
 481         if (IN6_IS_ADDR_V4MAPPED(vl3ip) == 0) {
 482                 return;
 483         } else {
 484                 IN6_V4MAPPED_TO_INADDR(vl3ip, &v4);
 485                 if (targmac == NULL)
 486                         targmac = svp_bcast;
 487                 libvarpd_inject_arp(svp->svp_hdl, vlan, vl2mac, &v4, targmac);
 488         }
 489 }
 490 
 491 /* ARGSUSED */
 492 static void
 493 svp_shootdown_cb(svp_t *svp, const uint8_t *vl2mac, const struct in6_addr *uip,
 494     const uint16_t uport)
 495 {
 496         /*
 497          * We should probably do a conditional invlaidation here.
 498          */
 499         libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
 500 }
 501 
 502 static void
 503 svp_rvl3_lookup_cb(svp_t *svp, svp_status_t status, /* XXX KEBE SAYS MORE */


 504     void *arg)
 505 {
 506         svp_lookup_t *svl = arg;
 507         overlay_target_point_t *otp;
 508         overlay_target_route_t *otr;
 509 
 510         if (status != SVP_S_OK) {
 511                 libvarpd_plugin_query_reply(svl->svl_u.svl_rvl3.svl_handle,
 512                     VARPD_LOOKUP_DROP);
 513                 umem_cache_free(svp_lookup_cache, svl);
 514                 return;
 515         }
 516 
 517         otp = svl->svl_u.svl_rvl3.svl_point;
 518         otr = svl->svl_u.svl_rvl3.svl_route;
 519         /* XXX KEBE SAYS FILL ME IN! */

 520 
 521         libvarpd_plugin_query_reply(svl->svl_u.svl_rvl3.svl_handle,








 522             VARPD_LOOKUP_OK);
 523         umem_cache_free(svp_lookup_cache, svl);
 524 }
 525 
 526 static svp_cb_t svp_defops = {
 527         svp_vl2_lookup_cb,
 528         svp_vl3_lookup_cb,
 529         svp_vl2_invalidate_cb,
 530         svp_vl3_inject_cb,
 531         svp_shootdown_cb,
 532         svp_rvl3_lookup_cb,
 533 };
 534 
 535 static boolean_t
 536 varpd_svp_valid_dest(overlay_plugin_dest_t dest)
 537 {
 538         if (dest != (OVERLAY_PLUGIN_D_IP | OVERLAY_PLUGIN_D_PORT))
 539                 return (B_FALSE);
 540 
 541         return (B_TRUE);
 542 }
 543 
 544 static int
 545 varpd_svp_create(varpd_provider_handle_t *hdl, void **outp,
 546     overlay_plugin_dest_t dest)
 547 {
 548         int ret;
 549         svp_t *svp;
 550 
 551         if (varpd_svp_valid_dest(dest) == B_FALSE)
 552                 return (ENOTSUP);


 620 }
 621 
 622 static void
 623 varpd_svp_lookup_l3(svp_t *svp, varpd_query_handle_t *vqh,
 624     const overlay_targ_lookup_t *otl, overlay_target_point_t *otp,
 625     overlay_target_route_t *otr)
 626 {
 627         svp_lookup_t *slp;
 628         uint32_t type;
 629         const struct in6_addr *src = &otl->otl_addru.otlu_l3.otl3_srcip,
 630             *dst = &otl->otl_addru.otlu_l3.otl3_dstip;
 631 
 632         /*
 633          * otl is an L3 request, so we have src/dst IPs for the inner packet.
 634          * We also have the vlan.
 635          *
 636          * Assume kernel's overlay module is caching well, so we are directly
 637          * going to query (i.e. no caching up here of actual destinations).
 638          *
 639          * Our existing remote sever (svp_remote), but with the new message
 640          * SVP_R_REMOTE_VL3_REQ.  Our naming of these functions already has
 641          * "remote" in it, but we'll use "rvl3" instead of "vl3".
 642          */
 643 
 644         /* XXX KEBE SAYS DO SOME otl verification too... */
 645         if (IN6_IS_ADDR_V4MAPPED(src)) {
 646                 if (!IN6_IS_ADDR_V4MAPPED(dst)) {
 647                         libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
 648                         return;
 649                 }
 650                 type = SVP_VL3_IP;
 651         } else {
 652                 if (IN6_IS_ADDR_V4MAPPED(dst)) {
 653                         libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
 654                         return;
 655                 }
 656                 type = SVP_VL3_IPV6;
 657         }
 658 
 659         slp = umem_cache_alloc(svp_lookup_cache, UMEM_DEFAULT);
 660         if (slp == NULL) {
 661                 libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
 662                 return;
 663         }
 664 
 665         slp->svl_type = SVP_L_RVL3;
 666         slp->svl_u.svl_rvl3.svl_handle = vqh;
 667         slp->svl_u.svl_rvl3.svl_point = otp;
 668         slp->svl_u.svl_rvl3.svl_route = otr;
 669 
 670         /* XXX KEBE SAYS FILL IN ARGS PROPERLY... */
 671         svp_remote_rvl3_lookup(svp, &slp->svl_query, src, dst, type,
 672             otl->otl_vnetid, (uint16_t)otl->otl_vlan, slp);
 673 }
 674 
 675 static void
 676 varpd_svp_lookup(void *arg, varpd_query_handle_t *vqh,
 677     const overlay_targ_lookup_t *otl, overlay_target_point_t *otp,
 678     overlay_target_route_t *otr)
 679 {
 680         svp_lookup_t *slp;
 681         svp_t *svp = arg;
 682 
 683         /*
 684          * Shuffle off L3 lookups to their own codepath.
 685          */
 686         if (otl->otl_l3req) {
 687                 varpd_svp_lookup_l3(svp, vqh, otl, otp, otr);
 688                 return;
 689         }
 690         /*
 691          * At this point, the traditional overlay_target_point_t is all that


 783                 break;
 784         case 3:
 785                 /* svp/underlay_port */
 786                 libvarpd_prop_set_name(vph, varpd_svp_props[3]);
 787                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
 788                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
 789                 (void) libvarpd_prop_set_default(vph, &svp_defuport,
 790                     sizeof (svp_defuport));
 791                 libvarpd_prop_set_range_uint32(vph, 1, UINT16_MAX);
 792                 break;
 793         case 4:
 794                 /* svp/dcid */
 795                 libvarpd_prop_set_name(vph, varpd_svp_props[4]);
 796                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
 797                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
 798                 libvarpd_prop_set_nodefault(vph);
 799                 /* XXX KEBE ASKS should I just set high to UINT32_MAX? */
 800                 libvarpd_prop_set_range_uint32(vph, 1, UINT32_MAX - 1);
 801                 break;
 802         case 5:
 803                 /* svp/router_mac */
 804                 libvarpd_prop_set_name(vph, varpd_svp_props[5]);
 805                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
 806                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_ETHER);
 807                 libvarpd_prop_set_nodefault(vph);
 808                 break;
 809         default:
 810                 return (EINVAL);
 811         }
 812         return (0);
 813 }
 814 
 815 static int
 816 varpd_svp_getprop(void *arg, const char *pname, void *buf, uint32_t *sizep)
 817 {
 818         svp_t *svp = arg;
 819 
 820         /* svp/host */
 821         if (strcmp(pname, varpd_svp_props[0]) == 0) {
 822                 size_t len;
 823 


 894         /* svp/dcid */
 895         if (strcmp(pname, varpd_svp_props[4]) == 0) {
 896                 uint64_t val;
 897 
 898                 if (*sizep < sizeof (uint64_t))
 899                         return (EOVERFLOW);
 900 
 901                 mutex_enter(&svp->svp_lock);
 902                 if (svp->svp_uport == 0) {
 903                         *sizep = 0;
 904                 } else {
 905                         val = svp->svp_dcid;
 906                         bcopy(&val, buf, sizeof (uint64_t));
 907                         *sizep = sizeof (uint64_t);
 908                 }
 909 
 910                 mutex_exit(&svp->svp_lock);
 911                 return (0);
 912         }
 913 
 914         /* svp/router_mac */
 915         if (strcmp(pname, varpd_svp_props[5]) == 0) {
 916                 if (*sizep < ETHERADDRL)
 917                         return (EOVERFLOW);
 918                 mutex_enter(&svp->svp_lock);
 919 
 920                 if (ether_is_zero(&svp->svp_router_mac)) {
 921                         *sizep = 0;
 922                 } else {
 923                         bcopy(&svp->svp_router_mac, buf, ETHERADDRL);
 924                         *sizep = ETHERADDRL;
 925                 }
 926 
 927                 mutex_exit(&svp->svp_lock);
 928                 return (0);
 929         }
 930         return (EINVAL);
 931 }
 932 
 933 static int
 934 varpd_svp_setprop(void *arg, const char *pname, const void *buf,
 935     const uint32_t size)
 936 {
 937         svp_t *svp = arg;
 938 
 939         /* svp/host */
 940         if (strcmp(pname, varpd_svp_props[0]) == 0) {
 941                 char *dup;
 942                 dup = umem_alloc(size, UMEM_DEFAULT);
 943                 (void) strlcpy(dup, buf, size);


1012                 return (0);
1013         }
1014 
1015         /* svp/dcid */
1016         if (strcmp(pname, varpd_svp_props[4]) == 0) {
1017                 const uint64_t *valp = buf;
1018                 if (size < sizeof (uint64_t))
1019                         return (EOVERFLOW);
1020 
1021                 /* XXX KEBE ASKS, use UINT32_MAX instead? */
1022                 if (*valp == 0 || *valp > UINT32_MAX - 1)
1023                         return (EINVAL);
1024 
1025                 mutex_enter(&svp->svp_lock);
1026                 svp->svp_dcid = (uint32_t)*valp;
1027                 mutex_exit(&svp->svp_lock);
1028 
1029                 return (0);
1030         }
1031 
1032         /* svp/router_mac */
1033         if (strcmp(pname, varpd_svp_props[5]) == 0) {
1034                 if (size < ETHERADDRL)
1035                         return (EOVERFLOW);
1036                 mutex_enter(&svp->svp_lock);
1037                 bcopy(buf, &svp->svp_router_mac, ETHERADDRL);




1038                 mutex_exit(&svp->svp_lock);
1039                 return (0);
1040         }
1041 
1042         return (EINVAL);
1043 }
1044 
1045 static int
1046 varpd_svp_save(void *arg, nvlist_t *nvp)
1047 {
1048         int ret;
1049         svp_t *svp = arg;
1050 
1051         mutex_enter(&svp->svp_lock);
1052         /* svp/host */
1053         if (svp->svp_host != NULL) {
1054                 if ((ret = nvlist_add_string(nvp, varpd_svp_props[0],
1055                     svp->svp_host)) != 0) {
1056                         mutex_exit(&svp->svp_lock);
1057                         return (ret);


1084         }
1085 
1086         /* svp/underlay_port */
1087         if (svp->svp_uport != 0) {
1088                 if ((ret = nvlist_add_uint16(nvp, varpd_svp_props[3],
1089                     svp->svp_uport)) != 0) {
1090                         mutex_exit(&svp->svp_lock);
1091                         return (ret);
1092                 }
1093         }
1094 
1095         /* svp/dcid */
1096         if (svp->svp_dcid != 0) {
1097                 if ((ret = nvlist_add_uint32(nvp, varpd_svp_props[4],
1098                     svp->svp_dcid)) != 0) {
1099                         mutex_exit(&svp->svp_lock);
1100                         return (ret);
1101                 }
1102         }
1103 
1104         /* svp/router_mac */
1105         if (!ether_is_zero(&svp->svp_router_mac)) {
1106                 char buf[ETHERADDRSTRL];
1107 
1108                 /* XXX KEBE SAYS See underlay_ip... */
1109                 if (ether_ntoa_r(&svp->svp_router_mac, buf) == NULL) {

1110                         libvarpd_panic("unexpected ether_ntoa_r failure: %d",
1111                             errno);
1112                 }
1113 
1114                 if ((ret = nvlist_add_string(nvp, varpd_svp_props[5],
1115                     buf)) != 0) {
1116                         mutex_exit(&svp->svp_lock);
1117                         return (ret);
1118                 }
1119         }
1120 
1121         mutex_exit(&svp->svp_lock);
1122         return (0);
1123 }
1124 
1125 static int
1126 varpd_svp_restore(nvlist_t *nvp, varpd_provider_handle_t *hdl,
1127     overlay_plugin_dest_t dest, void **outp)
1128 {
1129         int ret;


1186         /* svp/underlay_port */
1187         if ((ret = nvlist_lookup_uint16(nvp, varpd_svp_props[3],
1188             &svp->svp_uport)) != 0) {
1189                 if (ret != ENOENT) {
1190                         varpd_svp_destroy(svp);
1191                         return (ret);
1192                 }
1193                 svp->svp_uport = 0;
1194         }
1195 
1196         /* svp/dcid */
1197         if ((ret = nvlist_lookup_uint32(nvp, varpd_svp_props[4],
1198             &svp->svp_dcid)) != 0) {
1199                 if (ret != ENOENT) {
1200                         varpd_svp_destroy(svp);
1201                         return (ret);
1202                 }
1203                 svp->svp_dcid = 0;
1204         }
1205 
1206         /* svp/router_mac */
1207         if ((ret = nvlist_lookup_string(nvp, varpd_svp_props[5],
1208             &etherstr)) != 0) {
1209                 if (ret != ENOENT) {
1210                         varpd_svp_destroy(svp);
1211                         return (ret);
1212                 }
1213                 bzero(&svp->svp_router_mac, ETHERADDRL);
1214         } else if (ether_aton_r(etherstr, &svp->svp_router_mac) == NULL) {

1215                 libvarpd_panic("unexpected ether_aton_r failure: %d", errno);
1216         }
1217 
1218         svp->svp_hdl = hdl;
1219         *outp = svp;
1220         return (0);
1221 }
1222 
1223 static void
1224 varpd_svp_arp(void *arg, varpd_arp_handle_t *vah, int type,
1225     const struct sockaddr *sock, uint8_t *out)
1226 {
1227         svp_t *svp = arg;
1228         svp_lookup_t *svl;
1229 
1230         if (type != VARPD_QTYPE_ETHERNET) {
1231                 libvarpd_plugin_arp_reply(vah, VARPD_LOOKUP_DROP);
1232                 return;
1233         }
1234 




 344 #include <netinet/in.h>
 345 #include <arpa/inet.h>
 346 #include <libnvpair.h>
 347 #include <strings.h>
 348 #include <string.h>
 349 #include <assert.h>
 350 #include <unistd.h>
 351 
 352 #include <libvarpd_provider.h>
 353 #include "libvarpd_svp.h"
 354 
 355 bunyan_logger_t *svp_bunyan;
 356 static int svp_defport = 1296;
 357 static int svp_defuport = 1339;
 358 static umem_cache_t *svp_lookup_cache;
 359 
 360 typedef enum svp_lookup_type {
 361         SVP_L_UNKNOWN   = 0x0,
 362         SVP_L_VL2       = 0x1,
 363         SVP_L_VL3       = 0x2,
 364         SVP_L_ROUTE     = 0x3
 365 } svp_lookup_type_t;
 366 
 367 typedef struct svp_lookup {
 368         int svl_type;
 369         union {
 370                 struct svl_lookup_vl2 {
 371                         varpd_query_handle_t    *svl_handle;
 372                         overlay_target_point_t  *svl_point;
 373                 } svl_vl2;
 374                 struct svl_lookup_vl3 {
 375                         varpd_arp_handle_t      *svl_vah;
 376                         uint8_t                 *svl_out;
 377                 } svl_vl3;
 378                 struct svl_lookup_route {
 379                         varpd_query_handle_t    *svl_handle;
 380                         overlay_target_point_t  *svl_point;
 381                         overlay_target_route_t  *svl_route;
 382                 } svl_route;
 383         } svl_u;
 384         svp_query_t                             svl_query;
 385 } svp_lookup_t;
 386 
 387 static const char *varpd_svp_props[] = {
 388         "svp/host",
 389         "svp/port",
 390         "svp/underlay_ip",
 391         "svp/underlay_port",
 392         "svp/dcid",
 393         "svp/router_oui"
 394 };
 395 
 396 static const uint8_t svp_bcast[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 397 
 398 int
 399 svp_comparator(const void *l, const void *r)
 400 {
 401         const svp_t *ls = l;
 402         const svp_t *rs = r;
 403 
 404         if (ls->svp_vid > rs->svp_vid)
 405                 return (1);
 406         if (ls->svp_vid < rs->svp_vid)
 407                 return (-1);
 408         return (0);
 409 }
 410 
 411 static void
 412 svp_vl2_lookup_cb(svp_t *svp, svp_status_t status, const struct in6_addr *uip,
 413     const uint16_t uport, void *arg)


 420 
 421         if (status != SVP_S_OK) {
 422                 libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
 423                     VARPD_LOOKUP_DROP);
 424                 umem_cache_free(svp_lookup_cache, svl);
 425                 return;
 426         }
 427 
 428         otp = svl->svl_u.svl_vl2.svl_point;
 429         bcopy(uip, &otp->otp_ip, sizeof (struct in6_addr));
 430         otp->otp_port = uport;
 431         libvarpd_plugin_query_reply(svl->svl_u.svl_vl2.svl_handle,
 432             VARPD_LOOKUP_OK);
 433         umem_cache_free(svp_lookup_cache, svl);
 434 }
 435 
 436 static void
 437 svp_vl3_lookup_cb(svp_t *svp, svp_status_t status, const uint8_t *vl2mac,
 438     const struct in6_addr *uip, const uint16_t uport, void *arg)
 439 {
 440         /* Initialize address-holders to 0 for comparisons-to-zeroes later. */
 441         overlay_target_point_t point = { 0 };
 442         svp_lookup_t *svl = arg;
 443         uint8_t nexthop_mac[6] = { 0, 0, 0, 0, 0, 0 };
 444 
 445         assert(svp != NULL);
 446         assert(svl != NULL);
 447 
 448         if (status != SVP_S_OK) {
 449                 libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
 450                     VARPD_LOOKUP_DROP);
 451                 umem_cache_free(svp_lookup_cache, svl);
 452                 return;
 453         }
 454 
 455         /* Inject the L2 mapping before the L3 */
 456         if (uport != 0 &&
 457             bcmp(uip, &point.otp_ip, sizeof (struct in6_addr)) != 0) {
 458                 /* Normal L3 lookup result... */
 459                 bcopy(uip, &point.otp_ip, sizeof (struct in6_addr));
 460                 point.otp_port = uport;
 461                 libvarpd_inject_varp(svp->svp_hdl, vl2mac, &point);
 462         } else {
 463                 /*
 464                  * Oh my, we have a next-hop router IP.
 465                  * Set the MAC to the ouid+vid concatenated
 466                  * special-router-MAC. Overlay down below will know
 467                  * that uport == 0 means the MAC is a special one.
 468                  */
 469                 if (bcmp(svp->svp_router_oui, nexthop_mac, ETHERADDRL) == 0) {
 470                         /*
 471                          * We don't have a router_oui, so we can't support
 472                          * special-router-MAC.  Drop it.
 473                          */
 474                         libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
 475                             VARPD_LOOKUP_DROP);
 476                         umem_cache_free(svp_lookup_cache, svl);
 477                         return;
 478                 }
 479                 bcopy(svp->svp_router_oui, nexthop_mac, 3);
 480                 nexthop_mac[3] = (svp->svp_vid >> 16) & 0xff;
 481                 nexthop_mac[4] = (svp->svp_vid >> 8) & 0xff;
 482                 nexthop_mac[5] = svp->svp_vid & 0xff;
 483                 vl2mac = nexthop_mac;
 484         }
 485 
 486         bcopy(vl2mac, svl->svl_u.svl_vl3.svl_out, ETHERADDRL);
 487         libvarpd_plugin_arp_reply(svl->svl_u.svl_vl3.svl_vah,
 488             VARPD_LOOKUP_OK);
 489         umem_cache_free(svp_lookup_cache, svl);
 490 }
 491 
 492 static void
 493 svp_vl2_invalidate_cb(svp_t *svp, const uint8_t *vl2mac)
 494 {
 495         libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
 496 }
 497 
 498 static void
 499 svp_vl3_inject_cb(svp_t *svp, const uint16_t vlan, const struct in6_addr *vl3ip,
 500     const uint8_t *vl2mac, const uint8_t *targmac)
 501 {
 502         struct in_addr v4;
 503 
 504         /*
 505          * At the moment we don't support any IPv6 related log entries, this
 506          * will change soon as we develop a bit more of the IPv6 related
 507          * infrastructure so we can properly test the injection.
 508          */
 509         if (IN6_IS_ADDR_V4MAPPED(vl3ip) == 0) {
 510                 return;
 511         } else {
 512                 IN6_V4MAPPED_TO_INADDR(vl3ip, &v4);
 513                 if (targmac == NULL)
 514                         targmac = svp_bcast;
 515                 libvarpd_inject_arp(svp->svp_hdl, vlan, vl2mac, &v4, targmac);
 516         }
 517 }
 518 
 519 /* ARGSUSED */
 520 static void
 521 svp_shootdown_cb(svp_t *svp, const uint8_t *vl2mac, const struct in6_addr *uip,
 522     const uint16_t uport)
 523 {
 524         /*
 525          * We should probably do a conditional invalidation here.
 526          */
 527         libvarpd_inject_varp(svp->svp_hdl, vl2mac, NULL);
 528 }
 529 
 530 static void
 531 svp_route_lookup_cb(svp_t *svp, svp_status_t status, uint32_t dcid,
 532     uint32_t vnetid, uint16_t vlan, uint8_t *srcmac, uint8_t *dstmac,
 533     uint16_t ul3_port, uint8_t *ul3_addr, uint8_t srcpfx, uint8_t dstpfx,
 534     void *arg)
 535 {
 536         svp_lookup_t *svl = arg;
 537         overlay_target_point_t *otp;
 538         overlay_target_route_t *otr;
 539 
 540         if (status != SVP_S_OK) {
 541                 libvarpd_plugin_query_reply(svl->svl_u.svl_route.svl_handle,
 542                     VARPD_LOOKUP_DROP);
 543                 umem_cache_free(svp_lookup_cache, svl);
 544                 return;
 545         }
 546 
 547         otp = svl->svl_u.svl_route.svl_point;
 548         bcopy(dstmac, otp->otp_mac, ETHERADDRL);
 549         bcopy(ul3_addr, &otp->otp_ip, sizeof (struct in6_addr));
 550         otp->otp_port = ul3_port;
 551 
 552         otr = svl->svl_u.svl_route.svl_route;
 553         otr->otr_vnet = vnetid;
 554         otr->otr_vlan = vlan;
 555         bcopy(srcmac, otr->otr_srcmac, ETHERADDRL);
 556         otr->otr_dcid = dcid;
 557         otr->otr_src_prefixlen = srcpfx;
 558         otr->otr_dst_prefixlen = dstpfx;
 559 
 560         libvarpd_plugin_query_reply(svl->svl_u.svl_route.svl_handle,
 561             VARPD_LOOKUP_OK);
 562         umem_cache_free(svp_lookup_cache, svl);
 563 }
 564 
 565 static svp_cb_t svp_defops = {
 566         svp_vl2_lookup_cb,
 567         svp_vl3_lookup_cb,
 568         svp_vl2_invalidate_cb,
 569         svp_vl3_inject_cb,
 570         svp_shootdown_cb,
 571         svp_route_lookup_cb,
 572 };
 573 
 574 static boolean_t
 575 varpd_svp_valid_dest(overlay_plugin_dest_t dest)
 576 {
 577         if (dest != (OVERLAY_PLUGIN_D_IP | OVERLAY_PLUGIN_D_PORT))
 578                 return (B_FALSE);
 579 
 580         return (B_TRUE);
 581 }
 582 
 583 static int
 584 varpd_svp_create(varpd_provider_handle_t *hdl, void **outp,
 585     overlay_plugin_dest_t dest)
 586 {
 587         int ret;
 588         svp_t *svp;
 589 
 590         if (varpd_svp_valid_dest(dest) == B_FALSE)
 591                 return (ENOTSUP);


 659 }
 660 
 661 static void
 662 varpd_svp_lookup_l3(svp_t *svp, varpd_query_handle_t *vqh,
 663     const overlay_targ_lookup_t *otl, overlay_target_point_t *otp,
 664     overlay_target_route_t *otr)
 665 {
 666         svp_lookup_t *slp;
 667         uint32_t type;
 668         const struct in6_addr *src = &otl->otl_addru.otlu_l3.otl3_srcip,
 669             *dst = &otl->otl_addru.otlu_l3.otl3_dstip;
 670 
 671         /*
 672          * otl is an L3 request, so we have src/dst IPs for the inner packet.
 673          * We also have the vlan.
 674          *
 675          * Assume kernel's overlay module is caching well, so we are directly
 676          * going to query (i.e. no caching up here of actual destinations).
 677          *
 678          * Our existing remote sever (svp_remote), but with the new message
 679          * SVP_R_ROUTE_REQ.

 680          */
 681 
 682         /* XXX KEBE SAYS DO SOME otl verification too... */
 683         if (IN6_IS_ADDR_V4MAPPED(src)) {
 684                 if (!IN6_IS_ADDR_V4MAPPED(dst)) {
 685                         libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
 686                         return;
 687                 }
 688                 type = SVP_VL3_IP;
 689         } else {
 690                 if (IN6_IS_ADDR_V4MAPPED(dst)) {
 691                         libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
 692                         return;
 693                 }
 694                 type = SVP_VL3_IPV6;
 695         }
 696 
 697         slp = umem_cache_alloc(svp_lookup_cache, UMEM_DEFAULT);
 698         if (slp == NULL) {
 699                 libvarpd_plugin_query_reply(vqh, VARPD_LOOKUP_DROP);
 700                 return;
 701         }
 702 
 703         slp->svl_type = SVP_L_ROUTE;
 704         slp->svl_u.svl_route.svl_handle = vqh;
 705         slp->svl_u.svl_route.svl_point = otp;
 706         slp->svl_u.svl_route.svl_route = otr;
 707 
 708         svp_remote_route_lookup(svp, &slp->svl_query, src, dst,

 709             otl->otl_vnetid, (uint16_t)otl->otl_vlan, slp);
 710 }
 711 
 712 static void
 713 varpd_svp_lookup(void *arg, varpd_query_handle_t *vqh,
 714     const overlay_targ_lookup_t *otl, overlay_target_point_t *otp,
 715     overlay_target_route_t *otr)
 716 {
 717         svp_lookup_t *slp;
 718         svp_t *svp = arg;
 719 
 720         /*
 721          * Shuffle off L3 lookups to their own codepath.
 722          */
 723         if (otl->otl_l3req) {
 724                 varpd_svp_lookup_l3(svp, vqh, otl, otp, otr);
 725                 return;
 726         }
 727         /*
 728          * At this point, the traditional overlay_target_point_t is all that


 820                 break;
 821         case 3:
 822                 /* svp/underlay_port */
 823                 libvarpd_prop_set_name(vph, varpd_svp_props[3]);
 824                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
 825                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
 826                 (void) libvarpd_prop_set_default(vph, &svp_defuport,
 827                     sizeof (svp_defuport));
 828                 libvarpd_prop_set_range_uint32(vph, 1, UINT16_MAX);
 829                 break;
 830         case 4:
 831                 /* svp/dcid */
 832                 libvarpd_prop_set_name(vph, varpd_svp_props[4]);
 833                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
 834                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_UINT);
 835                 libvarpd_prop_set_nodefault(vph);
 836                 /* XXX KEBE ASKS should I just set high to UINT32_MAX? */
 837                 libvarpd_prop_set_range_uint32(vph, 1, UINT32_MAX - 1);
 838                 break;
 839         case 5:
 840                 /* svp/router_oui */
 841                 libvarpd_prop_set_name(vph, varpd_svp_props[5]);
 842                 libvarpd_prop_set_prot(vph, OVERLAY_PROP_PERM_RRW);
 843                 libvarpd_prop_set_type(vph, OVERLAY_PROP_T_ETHER);
 844                 libvarpd_prop_set_nodefault(vph);
 845                 break;
 846         default:
 847                 return (EINVAL);
 848         }
 849         return (0);
 850 }
 851 
 852 static int
 853 varpd_svp_getprop(void *arg, const char *pname, void *buf, uint32_t *sizep)
 854 {
 855         svp_t *svp = arg;
 856 
 857         /* svp/host */
 858         if (strcmp(pname, varpd_svp_props[0]) == 0) {
 859                 size_t len;
 860 


 931         /* svp/dcid */
 932         if (strcmp(pname, varpd_svp_props[4]) == 0) {
 933                 uint64_t val;
 934 
 935                 if (*sizep < sizeof (uint64_t))
 936                         return (EOVERFLOW);
 937 
 938                 mutex_enter(&svp->svp_lock);
 939                 if (svp->svp_uport == 0) {
 940                         *sizep = 0;
 941                 } else {
 942                         val = svp->svp_dcid;
 943                         bcopy(&val, buf, sizeof (uint64_t));
 944                         *sizep = sizeof (uint64_t);
 945                 }
 946 
 947                 mutex_exit(&svp->svp_lock);
 948                 return (0);
 949         }
 950 
 951         /* svp/router_oui */
 952         if (strcmp(pname, varpd_svp_props[5]) == 0) {
 953                 if (*sizep < ETHERADDRL)
 954                         return (EOVERFLOW);
 955                 mutex_enter(&svp->svp_lock);
 956 
 957                 if (ether_is_zero(&svp->svp_router_oui)) {
 958                         *sizep = 0;
 959                 } else {
 960                         bcopy(&svp->svp_router_oui, buf, ETHERADDRL);
 961                         *sizep = ETHERADDRL;
 962                 }
 963 
 964                 mutex_exit(&svp->svp_lock);
 965                 return (0);
 966         }
 967         return (EINVAL);
 968 }
 969 
 970 static int
 971 varpd_svp_setprop(void *arg, const char *pname, const void *buf,
 972     const uint32_t size)
 973 {
 974         svp_t *svp = arg;
 975 
 976         /* svp/host */
 977         if (strcmp(pname, varpd_svp_props[0]) == 0) {
 978                 char *dup;
 979                 dup = umem_alloc(size, UMEM_DEFAULT);
 980                 (void) strlcpy(dup, buf, size);


1049                 return (0);
1050         }
1051 
1052         /* svp/dcid */
1053         if (strcmp(pname, varpd_svp_props[4]) == 0) {
1054                 const uint64_t *valp = buf;
1055                 if (size < sizeof (uint64_t))
1056                         return (EOVERFLOW);
1057 
1058                 /* XXX KEBE ASKS, use UINT32_MAX instead? */
1059                 if (*valp == 0 || *valp > UINT32_MAX - 1)
1060                         return (EINVAL);
1061 
1062                 mutex_enter(&svp->svp_lock);
1063                 svp->svp_dcid = (uint32_t)*valp;
1064                 mutex_exit(&svp->svp_lock);
1065 
1066                 return (0);
1067         }
1068 
1069         /* svp/router_oui */
1070         if (strcmp(pname, varpd_svp_props[5]) == 0) {
1071                 if (size < ETHERADDRL)
1072                         return (EOVERFLOW);
1073                 mutex_enter(&svp->svp_lock);
1074                 bcopy(buf, &svp->svp_router_oui, ETHERADDRL);
1075                 /* Zero-out the low three bytes. */
1076                 svp->svp_router_oui[3] = 0;
1077                 svp->svp_router_oui[4] = 0;
1078                 svp->svp_router_oui[5] = 0;
1079                 mutex_exit(&svp->svp_lock);
1080                 return (0);
1081         }
1082 
1083         return (EINVAL);
1084 }
1085 
1086 static int
1087 varpd_svp_save(void *arg, nvlist_t *nvp)
1088 {
1089         int ret;
1090         svp_t *svp = arg;
1091 
1092         mutex_enter(&svp->svp_lock);
1093         /* svp/host */
1094         if (svp->svp_host != NULL) {
1095                 if ((ret = nvlist_add_string(nvp, varpd_svp_props[0],
1096                     svp->svp_host)) != 0) {
1097                         mutex_exit(&svp->svp_lock);
1098                         return (ret);


1125         }
1126 
1127         /* svp/underlay_port */
1128         if (svp->svp_uport != 0) {
1129                 if ((ret = nvlist_add_uint16(nvp, varpd_svp_props[3],
1130                     svp->svp_uport)) != 0) {
1131                         mutex_exit(&svp->svp_lock);
1132                         return (ret);
1133                 }
1134         }
1135 
1136         /* svp/dcid */
1137         if (svp->svp_dcid != 0) {
1138                 if ((ret = nvlist_add_uint32(nvp, varpd_svp_props[4],
1139                     svp->svp_dcid)) != 0) {
1140                         mutex_exit(&svp->svp_lock);
1141                         return (ret);
1142                 }
1143         }
1144 
1145         /* svp/router_oui */
1146         if (!ether_is_zero(&svp->svp_router_oui)) {
1147                 char buf[ETHERADDRSTRL];
1148 
1149                 /* XXX KEBE SAYS See underlay_ip... */
1150                 if (ether_ntoa_r((struct ether_addr *)&svp->svp_router_oui,
1151                     buf) == NULL) {
1152                         libvarpd_panic("unexpected ether_ntoa_r failure: %d",
1153                             errno);
1154                 }
1155 
1156                 if ((ret = nvlist_add_string(nvp, varpd_svp_props[5],
1157                     buf)) != 0) {
1158                         mutex_exit(&svp->svp_lock);
1159                         return (ret);
1160                 }
1161         }
1162 
1163         mutex_exit(&svp->svp_lock);
1164         return (0);
1165 }
1166 
1167 static int
1168 varpd_svp_restore(nvlist_t *nvp, varpd_provider_handle_t *hdl,
1169     overlay_plugin_dest_t dest, void **outp)
1170 {
1171         int ret;


1228         /* svp/underlay_port */
1229         if ((ret = nvlist_lookup_uint16(nvp, varpd_svp_props[3],
1230             &svp->svp_uport)) != 0) {
1231                 if (ret != ENOENT) {
1232                         varpd_svp_destroy(svp);
1233                         return (ret);
1234                 }
1235                 svp->svp_uport = 0;
1236         }
1237 
1238         /* svp/dcid */
1239         if ((ret = nvlist_lookup_uint32(nvp, varpd_svp_props[4],
1240             &svp->svp_dcid)) != 0) {
1241                 if (ret != ENOENT) {
1242                         varpd_svp_destroy(svp);
1243                         return (ret);
1244                 }
1245                 svp->svp_dcid = 0;
1246         }
1247 
1248         /* svp/router_oui */
1249         if ((ret = nvlist_lookup_string(nvp, varpd_svp_props[5],
1250             &etherstr)) != 0) {
1251                 if (ret != ENOENT) {
1252                         varpd_svp_destroy(svp);
1253                         return (ret);
1254                 }
1255                 bzero(&svp->svp_router_oui, ETHERADDRL);
1256         } else if (ether_aton_r(etherstr,
1257             (struct ether_addr *)&svp->svp_router_oui) == NULL) {
1258                 libvarpd_panic("unexpected ether_aton_r failure: %d", errno);
1259         }
1260 
1261         svp->svp_hdl = hdl;
1262         *outp = svp;
1263         return (0);
1264 }
1265 
1266 static void
1267 varpd_svp_arp(void *arg, varpd_arp_handle_t *vah, int type,
1268     const struct sockaddr *sock, uint8_t *out)
1269 {
1270         svp_t *svp = arg;
1271         svp_lookup_t *svl;
1272 
1273         if (type != VARPD_QTYPE_ETHERNET) {
1274                 libvarpd_plugin_arp_reply(vah, VARPD_LOOKUP_DROP);
1275                 return;
1276         }
1277