Print this page
Factor out fixed/1-1 processing from vxlnat_vxlan_one(), paving way for
future processing types.
Initial definitions of NAT flows.


  79  * We will use this same AVL comparison function for many of these structures.
  80  */
  81 int
  82 vxlnat_tree_plus_in6_cmp(const void *first, const void *second)
  83 {
  84         in6_addr_t *firstaddr, *secondaddr;
  85         int ret;
  86 
  87         firstaddr = (in6_addr_t *)(((avl_node_t *)first) + 1);
  88         secondaddr = (in6_addr_t *)(((avl_node_t *)second) + 1);
  89 
  90         ret = memcmp(firstaddr, secondaddr, sizeof (in6_addr_t));
  91         if (ret > 0)
  92                 return (1);
  93         if (ret < 0)
  94                 return (-1);
  95         return (0);
  96 }
  97 
  98 /*































  99  * Find-and-reference-hold a vnet.  If none present, create one.
 100  * "vnetid" MUST be in wire-order and its one byte cleared.
 101  */
 102 vxlnat_vnet_t *
 103 vxlnat_get_vnet(uint32_t vnetid, boolean_t create_on_miss)
 104 {
 105         vxlnat_vnet_t *vnet, searcher;
 106         avl_index_t where;
 107 
 108         /* Cheesy, but we KNOW vxnv_vnetid is the only thing checked. */
 109         searcher.vxnv_vnetid = vnetid;
 110 
 111         rw_enter(&vxlnat_vnet_lock, create_on_miss ? RW_WRITER : RW_READER);
 112         vnet = (vxlnat_vnet_t *)avl_find(&vxlnat_vnets, &searcher, &where);
 113         if (vnet == NULL && create_on_miss) {
 114                 vnet = kmem_zalloc(sizeof (*vnet), KM_SLEEP);
 115                 /* KM_SLEEP means non-NULL guaranteed. */
 116                 vnet->vxnv_refcount = 1; /* Internment reference. */
 117                 vnet->vxnv_vnetid = vnetid;
 118                 /* Initialize 1-1 mappings... */
 119                 rw_init(&vnet->vxnv_fixed_lock, NULL, RW_DRIVER, NULL);
 120                 avl_create(&vnet->vxnv_fixed_ips, vxlnat_tree_plus_in6_cmp,
 121                     sizeof (vxlnat_fixed_t), 0);
 122                 /* Initialize NAT rules.  (NAT mutex is zeroed-out.) */
 123                 list_create(&vnet->vxnv_rules, sizeof (vxlnat_rule_t), 0);
 124 #ifdef notyet
 125                 /* XXX KEBE SAYS INITIALIZE NAT flows... */
 126 #endif /* notyet */



 127                 /*
 128                  * Initialize remote VXLAN destination cache.
 129                  * (remotes mutex is zeroed-out.)
 130                  */
 131                 avl_create(&vnet->vxnv_remotes, vxlnat_tree_plus_in6_cmp,
 132                     sizeof (vxlnat_remote_t), 0);
 133 
 134                 avl_insert(&vxlnat_vnets, vnet, where);
 135         }
 136         if (vnet != NULL)
 137                 VXNV_REFHOLD(vnet);     /* Caller's reference. */
 138         rw_exit(&vxlnat_vnet_lock);
 139 
 140         return (vnet);
 141 }
 142 
 143 void
 144 vxlnat_vnet_free(vxlnat_vnet_t *vnet)
 145 {
 146         /* XXX KEBE SAYS FILL ME IN */


 417          * other {zones,machines} without triggering DAD.
 418          */
 419         if (ire->ire_type != IRE_LOCAL) {
 420                 ire_refrele(ire);
 421                 kmem_free(fixed, sizeof (*fixed));
 422                 rc = EADDRNOTAVAIL;     /* XXX KEBE ASKS different errno? */
 423                 goto fail;
 424         }
 425 
 426         /* Put the 1-1 mapping in place. */
 427         rw_enter(&vnet->vxnv_fixed_lock, RW_WRITER);
 428         if (avl_find(&vnet->vxnv_fixed_ips, fixed, &where) != NULL) {
 429                 /* Oh crap, we have an internal IP mapped already. */
 430                 ire_refrele(ire);
 431                 kmem_free(fixed, sizeof (*fixed));
 432                 rc = EEXIST;
 433         } else {
 434                 avl_insert(&vnet->vxnv_fixed_ips, fixed, where);
 435                 rc = 0;
 436                 /*
 437                  * CHEESY USE OF POINTERS WARNING: I'm going to use
 438                  * ire_dep_children for this IRE_LOCAL as a backpointer to
 439                  * this 'fixed'.  This'll allow rapid packet processing.
 440                  * Inspection seems to indicate that IRE_LOCAL ires NEVER use
 441                  * the ire_dep* pointers, so we'll use one (and independent of
 442                  * ip_stack_t's ips_ire_dep_lock as well).  If I'm wrong,
 443                  * fix it here and add a new pointer in ip.h for ire_t.
 444                  */
 445                 ire->ire_dep_sib_next = (ire_t *)fixed;


 446                 /* and then rewire the ire receive and send functions. */
 447                 if (ire->ire_ipversion == IPV4_VERSION) {
 448                         ire->ire_recvfn = vxlnat_fixed_ire_recv_v4;
 449                         ire->ire_sendfn = vxlnat_fixed_ire_send_v4;
 450                 } else {
 451                         ASSERT(ire->ire_ipversion == IPV6_VERSION);
 452                         ire->ire_recvfn = vxlnat_fixed_ire_recv_v6;
 453                         ire->ire_sendfn = vxlnat_fixed_ire_send_v6;
 454                 }
 455                 VXNF_REFHOLD(fixed);    /* ire holds us too... */
 456                 fixed->vxnf_ire = ire;
 457                 /*
 458                  * XXX KEBE SAYS CHEESY HACK:
 459                  */
 460                 if (!(ire->ire_ill->ill_flags & ILLF_ROUTER)) {
 461                         fixed->vxnf_clear_router = B_TRUE;
 462                         ire->ire_ill->ill_flags |= ILLF_ROUTER;
 463                 } else {
 464                         /* Just so we're clear... */
 465                         fixed->vxnf_clear_router = B_FALSE;
 466                 }

 467         }
 468         rw_exit(&vnet->vxnv_fixed_lock);
 469 
 470 fail:
 471         if (rc != 0)
 472                 vxlnat_public_rele(&vxnm->vxnm_public);
 473 
 474         return (rc);
 475 }
 476 
 477 static void
 478 vxlnat_rule_to_msg(vxn_msg_t *msg, vxlnat_rule_t *rule)
 479 {
 480         msg->vxnm_type = VXNM_RULE;
 481         msg->vxnm_vnetid = VXLAN_ID_NTOH(rule->vxnr_vnet->vxnv_vnetid);
 482         msg->vxnm_prefix = rule->vxnr_prefix;
 483         msg->vxnm_vlanid = ntohs(rule->vxnr_vlanid);
 484         bcopy(rule->vxnr_myether, msg->vxnm_ether_addr, ETHERADDRL);
 485         msg->vxnm_public = rule->vxnr_pubaddr;
 486         msg->vxnm_private = rule->vxnr_myaddr;




  79  * We will use this same AVL comparison function for many of these structures.
  80  */
  81 int
  82 vxlnat_tree_plus_in6_cmp(const void *first, const void *second)
  83 {
  84         in6_addr_t *firstaddr, *secondaddr;
  85         int ret;
  86 
  87         firstaddr = (in6_addr_t *)(((avl_node_t *)first) + 1);
  88         secondaddr = (in6_addr_t *)(((avl_node_t *)second) + 1);
  89 
  90         ret = memcmp(firstaddr, secondaddr, sizeof (in6_addr_t));
  91         if (ret > 0)
  92                 return (1);
  93         if (ret < 0)
  94                 return (-1);
  95         return (0);
  96 }
  97 
  98 /*
  99  * Comparison function for NAT flow.
 100  */
 101 static int
 102 vxlnat_flow_cmp_v4(const void *first, const void *second)
 103 {
 104         vxlnat_flow_t *first_flow = (vxlnat_flow_t *)first;
 105         vxlnat_flow_t *second_flow = (vxlnat_flow_t *)second;
 106         uint64_t firstaddrs, secondaddrs, firstportproto, secondportproto;
 107 
 108         firstaddrs = first_flow->vxnfl_src._S6_un._S6_u32[3] |
 109             (((uint64_t)first_flow->vxnfl_dst._S6_un._S6_u32[3]) << 32ULL);
 110         secondaddrs = second_flow->vxnfl_src._S6_un._S6_u32[3] |
 111             (((uint64_t)second_flow->vxnfl_dst._S6_un._S6_u32[3]) << 32ULL);
 112         firstportproto = first_flow->vxnfl_ports |
 113             (((uint64_t)first_flow->vxnfl_protocol) << 32ULL);
 114         secondportproto = second_flow->vxnfl_ports |
 115             (((uint64_t)second_flow->vxnfl_protocol) << 32ULL);
 116 
 117         if (firstaddrs > secondaddrs)
 118                 return (1);
 119         else if (firstaddrs < secondaddrs)
 120                 return (-1);
 121         else if (firstportproto > secondportproto)
 122                 return (1);
 123         else if (firstportproto < secondportproto)
 124                 return (-1);
 125 
 126         return (0);
 127 }
 128 
 129 /*
 130  * Find-and-reference-hold a vnet.  If none present, create one.
 131  * "vnetid" MUST be in wire-order and its one byte cleared.
 132  */
 133 vxlnat_vnet_t *
 134 vxlnat_get_vnet(uint32_t vnetid, boolean_t create_on_miss)
 135 {
 136         vxlnat_vnet_t *vnet, searcher;
 137         avl_index_t where;
 138 
 139         /* Cheesy, but we KNOW vxnv_vnetid is the only thing checked. */
 140         searcher.vxnv_vnetid = vnetid;
 141 
 142         rw_enter(&vxlnat_vnet_lock, create_on_miss ? RW_WRITER : RW_READER);
 143         vnet = (vxlnat_vnet_t *)avl_find(&vxlnat_vnets, &searcher, &where);
 144         if (vnet == NULL && create_on_miss) {
 145                 vnet = kmem_zalloc(sizeof (*vnet), KM_SLEEP);
 146                 /* KM_SLEEP means non-NULL guaranteed. */
 147                 vnet->vxnv_refcount = 1; /* Internment reference. */
 148                 vnet->vxnv_vnetid = vnetid;
 149                 /* Initialize 1-1 mappings... */
 150                 rw_init(&vnet->vxnv_fixed_lock, NULL, RW_DRIVER, NULL);
 151                 avl_create(&vnet->vxnv_fixed_ips, vxlnat_tree_plus_in6_cmp,
 152                     sizeof (vxlnat_fixed_t), 0);
 153                 /* Initialize NAT rules.  (NAT mutex is zeroed-out.) */
 154                 list_create(&vnet->vxnv_rules, sizeof (vxlnat_rule_t), 0);
 155 
 156                 /* Initialize NAT flows... */
 157                 rw_init(&vnet->vxnv_flowv4_lock, NULL, RW_DRIVER, NULL);
 158                 avl_create(&vnet->vxnv_flows_v4, vxlnat_flow_cmp_v4,
 159                     sizeof (vxlnat_flow_t), 0);
 160 
 161                 /*
 162                  * Initialize remote VXLAN destination cache.
 163                  * (remotes mutex is zeroed-out.)
 164                  */
 165                 avl_create(&vnet->vxnv_remotes, vxlnat_tree_plus_in6_cmp,
 166                     sizeof (vxlnat_remote_t), 0);
 167 
 168                 avl_insert(&vxlnat_vnets, vnet, where);
 169         }
 170         if (vnet != NULL)
 171                 VXNV_REFHOLD(vnet);     /* Caller's reference. */
 172         rw_exit(&vxlnat_vnet_lock);
 173 
 174         return (vnet);
 175 }
 176 
 177 void
 178 vxlnat_vnet_free(vxlnat_vnet_t *vnet)
 179 {
 180         /* XXX KEBE SAYS FILL ME IN */


 451          * other {zones,machines} without triggering DAD.
 452          */
 453         if (ire->ire_type != IRE_LOCAL) {
 454                 ire_refrele(ire);
 455                 kmem_free(fixed, sizeof (*fixed));
 456                 rc = EADDRNOTAVAIL;     /* XXX KEBE ASKS different errno? */
 457                 goto fail;
 458         }
 459 
 460         /* Put the 1-1 mapping in place. */
 461         rw_enter(&vnet->vxnv_fixed_lock, RW_WRITER);
 462         if (avl_find(&vnet->vxnv_fixed_ips, fixed, &where) != NULL) {
 463                 /* Oh crap, we have an internal IP mapped already. */
 464                 ire_refrele(ire);
 465                 kmem_free(fixed, sizeof (*fixed));
 466                 rc = EEXIST;
 467         } else {
 468                 avl_insert(&vnet->vxnv_fixed_ips, fixed, where);
 469                 rc = 0;
 470                 /*
 471                  * ODD USE OF POINTERS WARNING: I'm going to use
 472                  * ire_dep_sib_next for this IRE_LOCAL as a backpointer to
 473                  * this 'fixed'.  This'll allow rapid packet processing.
 474                  * Inspection seems to indicate that IRE_LOCAL ires NEVER use
 475                  * the ire_dep* pointers, so we'll use one (and independent of
 476                  * ip_stack_t's ips_ire_dep_lock as well).  If I'm wrong,
 477                  * fix it here and add a new pointer in ip.h for ire_t.
 478                  */
 479                 ire->ire_dep_sib_next = (ire_t *)fixed;
 480                 VXNF_REFHOLD(fixed);    /* ire holds us too... */
 481                 fixed->vxnf_ire = ire;
 482                 /* and then rewire the ire receive and send functions. */
 483                 if (ire->ire_ipversion == IPV4_VERSION) {
 484                         ire->ire_recvfn = vxlnat_fixed_ire_recv_v4;
 485                         ire->ire_sendfn = vxlnat_fixed_ire_send_v4;
 486                 } else {
 487                         ASSERT(ire->ire_ipversion == IPV6_VERSION);
 488                         ire->ire_recvfn = vxlnat_fixed_ire_recv_v6;
 489                         ire->ire_sendfn = vxlnat_fixed_ire_send_v6;
 490                 }
 491 #if 1   /* Cheesy hack */

 492                 /*
 493                  * XXX KEBE SAYS CHEESY HACK:
 494                  */
 495                 if (!(ire->ire_ill->ill_flags & ILLF_ROUTER)) {
 496                         fixed->vxnf_clear_router = B_TRUE;
 497                         ire->ire_ill->ill_flags |= ILLF_ROUTER;
 498                 } else {
 499                         /* Just so we're clear... */
 500                         fixed->vxnf_clear_router = B_FALSE;
 501                 }
 502 #endif  /* Cheesy hack */
 503         }
 504         rw_exit(&vnet->vxnv_fixed_lock);
 505 
 506 fail:
 507         if (rc != 0)
 508                 vxlnat_public_rele(&vxnm->vxnm_public);
 509 
 510         return (rc);
 511 }
 512 
 513 static void
 514 vxlnat_rule_to_msg(vxn_msg_t *msg, vxlnat_rule_t *rule)
 515 {
 516         msg->vxnm_type = VXNM_RULE;
 517         msg->vxnm_vnetid = VXLAN_ID_NTOH(rule->vxnr_vnet->vxnv_vnetid);
 518         msg->vxnm_prefix = rule->vxnr_prefix;
 519         msg->vxnm_vlanid = ntohs(rule->vxnr_vlanid);
 520         bcopy(rule->vxnr_myether, msg->vxnm_ether_addr, ETHERADDRL);
 521         msg->vxnm_public = rule->vxnr_pubaddr;
 522         msg->vxnm_private = rule->vxnr_myaddr;