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,366 ****
mp->b_rptr = (uint8_t *)ipha;
return (mp);
}
/*
* 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);
--- 347,461 ----
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;
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,510 ****
mp = mp->b_cont;
freeb(oldmp);
}
mp = vxlnat_cache_remote(mp, underlay_src, vnet);
! if (mp == NULL) {
! VXNV_REFRELE(vnet);
! return;
! }
! /* 2.) Search 1-1s, process if hit. */
ipha = (ipha_t *)mp->b_rptr;
! if (IPH_HDR_VERSION(ipha) == 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);
ip6h = (ip6_t *)ipha;
ipha = 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) {
- 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...
! */
! /* 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 */
! 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 };
! 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;
! }
! 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);
! }
!
! /* 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);
freemsg(mp);
}
/*
* ONLY return B_FALSE if we get a packet-clogging event.
*/
/* ARGSUSED */
--- 499,550 ----
mp = mp->b_cont;
freeb(oldmp);
}
mp = vxlnat_cache_remote(mp, underlay_src, vnet);
! if (mp == NULL)
! goto bail_no_free;
! /* Let's cache the IP header here... */
ipha = (ipha_t *)mp->b_rptr;
! switch (IPH_HDR_VERSION(ipha)) {
! case IPV4_VERSION:
ip6h = NULL;
! break;
! case IPV6_VERSION:
ip6h = (ip6_t *)ipha;
ipha = NULL;
! break;
! default:
! DTRACE_PROBE2(vxlnat__in__drop__ipvers, int,
! IPH_HDR_VERSION(ipha), mblk_t *, mp);
! goto bail_and_free;
}
! /* 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. */
! #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. */
! /* 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
! /* 5.) Nothing, drop the packet. */
! DTRACE_PROBE2(vxlnat__in___drop__nohits, vxlnat_vnet_t *, vnet,
! mblk_t *, mp);
! bail_and_free:
freemsg(mp);
+ bail_no_free:
+ VXNV_REFRELE(vnet);
}
/*
* ONLY return B_FALSE if we get a packet-clogging event.
*/
/* ARGSUSED */
*** 636,645 ****
--- 676,686 ----
}
/*
* 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;