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

@@ -347,20 +347,115 @@
         mp->b_rptr = (uint8_t *)ipha;
         return (mp);
 }
 
 /*
+ * See if the inbound VXLAN packet hits a 1-1/fixed mapping, and process if it
+ * does.  B_TRUE means the packet was handled, and we shouldn't continue
+ * processing (even if "was handled" means droppage).
+ */
+static boolean_t
+vxlnat_one_vxlan_fixed(vxlnat_vnet_t *vnet, mblk_t *mp, ipha_t *ipha,
+    ip6_t *ip6h)
+{
+        vxlnat_fixed_t *fixed, fsearch;
+        mblk_t *newmp;
+        ire_t *outbound_ire;
+        /* Use C99's initializers for fun & profit. */
+        ip_recv_attr_t iras = { IRAF_IS_IPV4 | IRAF_VERIFIED_SRC };
+
+        if (ipha != NULL) {
+                IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_src),
+                    &fsearch.vxnf_addr);
+        } else {
+                /* vxlnat_cache_remote() did reality checks... */
+                ASSERT(ipha == NULL && ip6h != NULL);
+                fsearch.vxnf_addr = ip6h->ip6_src;
+        }
+
+        rw_enter(&vnet->vxnv_fixed_lock, RW_READER);
+        fixed = avl_find(&vnet->vxnv_fixed_ips, &fsearch, NULL);
+        if (fixed != NULL)
+                VXNF_REFHOLD(fixed);
+        rw_exit(&vnet->vxnv_fixed_lock);
+        if (fixed == NULL)
+                return (B_FALSE);       /* Try another method of processing. */
+
+        newmp = NULL;
+        /*
+         * XXX KEBE ASKS --> Do an MTU check NOW?!  That way, we have
+         * pre-natted data.  One gotcha, external dests may have
+         * different PathMTUs so see below about EMSGSIZE...
+         *
+         * For now, let the post-NAT crunch through
+         * ire_recv_forward_v4() take care of all of that.
+         */
+
+        if (ipha != NULL)
+                newmp = vxlnat_fixed_fixv4(mp, fixed, B_FALSE);
+        else {
+                freemsg(mp); /* XXX handle ip6h */
+                return (B_TRUE);
+        }
+
+        if (newmp == NULL)
+                return (B_TRUE);        /* mp eaten by vxlnat_fixed_fixv4() */
+
+
+        ASSERT3P(ipha, ==, newmp->b_rptr);
+        /* XXX KEBE ASKS, IRR_ALLOCATE okay?!? */
+        /* XXX KEBE SAYS XMIT HINT! */
+        outbound_ire = ire_route_recursive_dstonly_v4(ipha->ipha_dst,
+            IRR_ALLOCATE, 0, vxlnat_netstack->netstack_ip);
+        VERIFY3P(outbound_ire, !=, NULL);
+        if (outbound_ire->ire_type == IRE_NOROUTE) {
+                /* Bail! */
+                DTRACE_PROBE2(vxlnat__in__drop__fixedire, ipaddr_t,
+                    ipha->ipha_dst, mblk_t *, mp);
+                VXNF_REFRELE(fixed);
+                freemsg(mp);
+                return (B_TRUE);
+        }
+
+        iras.ira_ip_hdr_length = IPH_HDR_LENGTH(ipha);
+        if (iras.ira_ip_hdr_length > sizeof (ipha_t))
+                iras.ira_flags |= IRAF_IPV4_OPTIONS;
+        iras.ira_xmit_hint = 0; /* XXX KEBE SAYS FIX ME! */
+        iras.ira_zoneid = outbound_ire->ire_zoneid;
+        iras.ira_pktlen = ntohs(ipha->ipha_length);
+        iras.ira_protocol = ipha->ipha_protocol;
+        /* XXX KEBE ASKS rifindex & ruifindex ?!? */
+        /*
+         * NOTE: AT LEAST ira_ill needs ILLF_ROUTER set, as
+         * well as the ill for the external NIC (where
+         * off-link destinations live).  For fixed, ira_ill
+         * should be the ill of the external source.
+         */
+        iras.ira_rill = vxlnat_underlay_ire->ire_ill;
+        iras.ira_ill = fixed->vxnf_ire->ire_ill;
+        /* XXX KEBE ASKS cred & cpid ? */
+        iras.ira_verified_src = ipha->ipha_src;
+        /* XXX KEBE SAYS don't sweat IPsec stuff. */
+        /* XXX KEBE SAYS ALSO don't sweat l2src & mhip */
+
+        /* Okay, we're good! Let's pretend we're forwarding. */
+        ire_recv_forward_v4(outbound_ire, mp, ipha, &iras);
+        ire_refrele(outbound_ire);
+
+        return (B_TRUE);
+}
+
+/*
  * Process exactly one VXLAN packet.
  */
 static void
 vxlnat_one_vxlan(mblk_t *mp, struct sockaddr_in6 *underlay_src)
 {
         vxlan_hdr_t *vxh;
         vxlnat_vnet_t *vnet;
         ipha_t *ipha;
         ip6_t *ip6h;
-        vxlnat_fixed_t *fixed, fsearch;
 
         if (MBLKL(mp) < sizeof (*vxh)) {
                 /* XXX KEBE ASKS -- should we be more forgiving? */
                 DTRACE_PROBE1(vxlnat__in__drop__vxlsize, mblk_t *, mp);
                 freemsg(mp);

@@ -404,107 +499,52 @@
 
                 mp = mp->b_cont;
                 freeb(oldmp);
         }
         mp = vxlnat_cache_remote(mp, underlay_src, vnet);
-        if (mp == NULL) {
-                VXNV_REFRELE(vnet);
-                return;
-        }
+        if (mp == NULL)
+                goto bail_no_free;
 
-        /* 2.) Search 1-1s, process if hit. */
+        /* Let's cache the IP header here... */
         ipha = (ipha_t *)mp->b_rptr;
-        if (IPH_HDR_VERSION(ipha) == IPV4_VERSION) {
+        switch (IPH_HDR_VERSION(ipha)) {
+        case IPV4_VERSION:
                 ip6h = NULL;
-                IN6_INADDR_TO_V4MAPPED((struct in_addr *)(&ipha->ipha_src),
-                    &fsearch.vxnf_addr);
-        } else {
-                /* vxlnat_cache_remote() did reality checks... */
-                ASSERT(IPH_HDR_VERSION(ipha) == IPV6_VERSION);
+                break;
+        case IPV6_VERSION:
                 ip6h = (ip6_t *)ipha;
                 ipha = NULL;
-                fsearch.vxnf_addr = ip6h->ip6_src;
+                break;
+        default:
+                DTRACE_PROBE2(vxlnat__in__drop__ipvers, int,
+                    IPH_HDR_VERSION(ipha), mblk_t *, mp);
+                goto bail_and_free;
         }
-        rw_enter(&vnet->vxnv_fixed_lock, RW_READER);
-        fixed = avl_find(&vnet->vxnv_fixed_ips, &fsearch, NULL);
-        if (fixed != NULL)
-                VXNF_REFHOLD(fixed);
-        rw_exit(&vnet->vxnv_fixed_lock);
-        if (fixed != NULL) {
-                mblk_t *newmp = NULL;
 
-                /*
-                 * XXX KEBE ASKS --> Do MTU check NOW?!  That way, we have
-                 * pre-natted data.  One gotcha, external dests may have
-                 * different PathMTUs so see below about EMSGSIZE...
-                 */
+        /* 2.) Search 1-1s, process if hit. */
+        if (vxlnat_one_vxlan_fixed(vnet, mp, ipha, ip6h))
+                goto bail_no_free;      /* Success means mp was consumed. */
 
-                /* XXX KEBE SAYS -- FILL ME IN... but for now: */
-                if (ipha != NULL)
-                        newmp = vxlnat_fixed_fixv4(mp, fixed, B_FALSE);
-                else
-                        freemsg(mp); /* XXX handle ip6h */
+#ifdef notyet
+        /* 3.) Search flows, process if hit. */
+        if (vxlnat_one_vxlan_flow(vnet, mp, ipha, ip6h))
+                goto bail_no_free;      /* Success means mp was consumed. */
 
-                if (newmp != NULL) {
-                        ire_t *outbound_ire;
-                        /* Use C99's initializers for fun & profit. */
-                        ip_recv_attr_t iras =
-                            { IRAF_IS_IPV4 | IRAF_VERIFIED_SRC };
+        /* 4.) Search rules, create new flow (or not) if hit. */
+        if (vxlnat_one_vxlan_rule(vnet, mp, ipha, ip6h))
+                goto bail_no_free;      /* Success means mp was consumed. */
+#endif
 
-                        ASSERT3P(ipha, !=, NULL);
-                        ASSERT3P(ipha, ==, newmp->b_rptr);
-                        /* XXX KEBE ASKS, IRR_ALLOCATE okay?!? */
-                        outbound_ire = ire_route_recursive_dstonly_v4(
-                            ipha->ipha_dst, IRR_ALLOCATE,
-                            0 /* XXX KEBE SAYS XMIT HINT! */,
-                            vxlnat_netstack->netstack_ip);
-                        VERIFY3P(outbound_ire, !=, NULL);
-                        if (outbound_ire->ire_type == IRE_NOROUTE) {
-                                /* Bail! */
-                                VXNF_REFRELE(fixed);
-                                VXNV_REFRELE(vnet);
-                                return;
-                        }
+        /* 5.) Nothing, drop the packet. */
 
-                        iras.ira_ip_hdr_length = IPH_HDR_LENGTH(ipha);
-                        if (iras.ira_ip_hdr_length > sizeof (ipha_t))
-                                iras.ira_flags |= IRAF_IPV4_OPTIONS;
-                        iras.ira_xmit_hint = 0; /* XXX KEBE SAYS FIX ME! */
-                        iras.ira_zoneid = outbound_ire->ire_zoneid;
-                        iras.ira_pktlen = ntohs(ipha->ipha_length);
-                        iras.ira_protocol = ipha->ipha_protocol;
-                        /* XXX KEBE ASKS rifindex & ruifindex ?!? */
-                        /*
-                         * NOTE: AT LEAST ira_ill needs ILLF_ROUTER set, as
-                         * well as the ill for the external NIC (where
-                         * off-link destinations live).  For fixed, ira_ill
-                         * should be the ill of the external source.
-                         */
-                        iras.ira_rill = vxlnat_underlay_ire->ire_ill;
-                        iras.ira_ill = fixed->vxnf_ire->ire_ill;
-                        /* XXX KEBE ASKS cred & cpid ? */
-                        iras.ira_verified_src = ipha->ipha_src;
-                        /* XXX KEBE SAYS don't sweat IPsec stuff. */
-                        /* XXX KEBE SAYS ALSO don't sweat l2src & mhip */
+        DTRACE_PROBE2(vxlnat__in___drop__nohits, vxlnat_vnet_t *, vnet,
+            mblk_t *, mp);
 
-                        /* Okay, we're good! Let's pretend we're forwarding. */
-                        ire_recv_forward_v4(outbound_ire, mp, ipha, &iras);
-                        ire_refrele(outbound_ire);
-                }
-
-                /* All done... */
-                VXNF_REFRELE(fixed);
-                VXNV_REFRELE(vnet);
-                return;
-        }
-
-        /* XXX KEBE SAYS BUILD STEPS 3-4. */
-
-        /* 5.) Nothing, drop the packet. */
-        /* XXX KEBE ASKS DIAGNOSTIC? */
-        VXNV_REFRELE(vnet);
+bail_and_free:
         freemsg(mp);
+bail_no_free:
+        VXNV_REFRELE(vnet);
 }
 /*
  * ONLY return B_FALSE if we get a packet-clogging event.
  */
 /* ARGSUSED */

@@ -636,10 +676,11 @@
 }
 
 /*
  * Take a 1-1/fixed IPv4 packet and convert it for transmission out the
  * appropriate end. "to_private" is what it says on the tin.
+ * ALWAYS consumes "mp", regardless of return value.
  */
 static mblk_t *
 vxlnat_fixed_fixv4(mblk_t *mp, vxlnat_fixed_t *fixed, boolean_t to_private)
 {
         ipaddr_t new_one, old_one;