From cb8d752c91e50d49493e6841a71a3add51e2f2da Mon Sep 17 00:00:00 2001 From: Nuno Antunes Date: Tue, 5 Aug 2008 15:11:32 +0000 Subject: [PATCH] * Don't call ifp->if_output() from inside mpls_output(). Make the caller responsible for sending the packet. * Fix mpls gateway arp resoving. * Introduce a new mbuf flag M_MPLSLABELED indicating that the packet has at least one valid mpls label on it. * Use the new mbuf flag instead of forging a sockaddr_mpls to let ether_output() identify the mpls packets. * Drop the packet when mpls ttl is exceeded (doesn't send an ICMP message yet). * Fix compilation warning. * Improve comments. --- sys/net/if_ethersubr.c | 39 ++++++-------------- sys/netinet/ip_output.c | 12 +++---- sys/netproto/mpls/mpls_demux.c | 3 +- sys/netproto/mpls/mpls_input.c | 21 +++++++---- sys/netproto/mpls/mpls_output.c | 64 +++++++++++++++++++-------------- sys/netproto/mpls/mpls_var.h | 11 +++--- sys/sys/mbuf.h | 5 +-- 7 files changed, 73 insertions(+), 82 deletions(-) diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 4dd688eaad..273037767b 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -32,7 +32,7 @@ * * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 * $FreeBSD: src/sys/net/if_ethersubr.c,v 1.70.2.33 2003/04/28 15:45:53 archie Exp $ - * $DragonFly: src/sys/net/if_ethersubr.c,v 1.81 2008/07/27 10:06:56 sephe Exp $ + * $DragonFly: src/sys/net/if_ethersubr.c,v 1.82 2008/08/05 15:11:32 nant Exp $ */ #include "opt_atalk.h" @@ -205,7 +205,12 @@ ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, case AF_INET: if (!arpresolve(ifp, rt, m, dst, edst)) return (0); /* if not yet resolved */ - eh->ether_type = htons(ETHERTYPE_IP); +#ifdef MPLS + if (m->m_flags & M_MPLSLABELED) + eh->ether_type = htons(ETHERTYPE_MPLS); + else +#endif + eh->ether_type = htons(ETHERTYPE_IP); break; #endif #ifdef INET6 @@ -304,33 +309,6 @@ ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, if (bcmp(edst, &ns_broadhost, ETHER_ADDR_LEN) == 0) m->m_flags |= M_BCAST; break; -#endif -#ifdef MPLS - case AF_MPLS: - { - struct sockaddr *sa_gw; - - if (rt) - sa_gw = (struct sockaddr *)rt->rt_gateway; - else { - /* We realy need a gateway. */ - m_freem(m); - return (0); - } - - switch (sa_gw->sa_family) { - case AF_INET: - if (!arpresolve(ifp, rt, m, sa_gw, edst)) - return (0); - break; - default: - kprintf("ether_output: address family not supported to forward mpls packets: %d.\n", sa_gw->sa_family); - m_freem(m); - return (0); - } - eh->ether_type = htons(ETHERTYPE_MPLS); /* XXX how about multicast? */ - break; - } #endif case pseudo_AF_HDRCMPLT: case AF_UNSPEC: @@ -1160,6 +1138,8 @@ post_stats: #ifdef MPLS case ETHERTYPE_MPLS: case ETHERTYPE_MPLS_MCAST: + /* Should have been set by ether_input_chain2(). */ + KKASSERT(m->m_flags & M_MPLSLABELED); isr = NETISR_MPLS; break; #endif @@ -1452,6 +1432,7 @@ ether_input_chain2(struct ifnet *ifp, struct mbuf *m, struct mbuf_chain *chain) #ifdef MPLS case ETHERTYPE_MPLS: case ETHERTYPE_MPLS_MCAST: + m->m_flags |= M_MPLSLABELED; isr = NETISR_MPLS; break; #endif diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index f7b0de58b5..7c2334f335 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -28,7 +28,7 @@ * * @(#)ip_output.c 8.3 (Berkeley) 1/21/94 * $FreeBSD: src/sys/netinet/ip_output.c,v 1.99.2.37 2003/04/15 06:44:45 silby Exp $ - * $DragonFly: src/sys/netinet/ip_output.c,v 1.46 2008/07/07 22:02:10 nant Exp $ + * $DragonFly: src/sys/netinet/ip_output.c,v 1.47 2008/08/05 15:11:32 nant Exp $ */ #define _IP_VHL @@ -1026,9 +1026,7 @@ pass: #endif #ifdef MPLS - struct rtentry *send_route = ro->ro_rt; /* copy-in/copy-out parameter */ - - if (!mpls_output_process(ifp, m, &dst, send_route)) + if (!mpls_output_process(m, ro->ro_rt)) goto done; #endif error = ifp->if_output(ifp, m, (struct sockaddr *)dst, @@ -1075,10 +1073,8 @@ pass: ia->ia_ifa.if_obytes += m->m_pkthdr.len; } #ifdef MPLS - struct rtentry *send_route = ro->ro_rt; /* copy-in/copy-out parameter */ - - if (!mpls_output_process(ifp, m, &dst, send_route)) - goto done; + if (!mpls_output_process(m, ro->ro_rt)) + goto done; #endif error = ifp->if_output(ifp, m, (struct sockaddr *)dst, ro->ro_rt); diff --git a/sys/netproto/mpls/mpls_demux.c b/sys/netproto/mpls/mpls_demux.c index af3051a837..447dcb0302 100644 --- a/sys/netproto/mpls/mpls_demux.c +++ b/sys/netproto/mpls/mpls_demux.c @@ -28,7 +28,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/netproto/mpls/mpls_demux.c,v 1.1 2008/07/07 22:02:10 nant Exp $ + * $DragonFly: src/sys/netproto/mpls/mpls_demux.c,v 1.2 2008/08/05 15:11:32 nant Exp $ */ #include @@ -106,4 +106,3 @@ mpls_mport(struct mbuf **mp) return (port); } - diff --git a/sys/netproto/mpls/mpls_input.c b/sys/netproto/mpls/mpls_input.c index 78a5916664..d5a1e041a1 100644 --- a/sys/netproto/mpls/mpls_input.c +++ b/sys/netproto/mpls/mpls_input.c @@ -28,7 +28,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/netproto/mpls/mpls_input.c,v 1.1 2008/07/07 22:02:10 nant Exp $ + * $DragonFly: src/sys/netproto/mpls/mpls_input.c,v 1.2 2008/08/05 15:11:32 nant Exp $ */ #include @@ -185,9 +185,10 @@ mpls_forward(struct mbuf *m) mpls_label_t label; struct ifnet *ifp; struct sockaddr *dst; + int error; KASSERT(m->m_len >= sizeof(struct mpls), - ("mpls_input: mpls header not in one mbuf")); + ("mpls_forward: mpls header not in one mbuf")); mpls = mtod(m, struct mpls *); label = MPLS_LABEL(ntohl(mpls->mpls_shim)); @@ -210,9 +211,15 @@ mpls_forward(struct mbuf *m) ifp = cache_rt->ro_rt->rt_ifp; dst = cache_rt->ro_rt->rt_gateway; - - if (mpls_output(ifp, m, dst, cache_rt->ro_rt) != 0) - m_freem(m); - else - mplsstat.mplss_forwarded++; + error = mpls_output(m, cache_rt->ro_rt); + if (error) + goto bad; + error = (*ifp->if_output)(ifp, m, dst, cache_rt->ro_rt); + if (error) + goto bad; + mplsstat.mplss_forwarded++; + + return; +bad: + m_freem(m); } diff --git a/sys/netproto/mpls/mpls_output.c b/sys/netproto/mpls/mpls_output.c index 1203ec6151..06946e3636 100644 --- a/sys/netproto/mpls/mpls_output.c +++ b/sys/netproto/mpls/mpls_output.c @@ -28,7 +28,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/netproto/mpls/mpls_output.c,v 1.1 2008/07/07 22:02:10 nant Exp $ + * $DragonFly: src/sys/netproto/mpls/mpls_output.c,v 1.2 2008/08/05 15:11:32 nant Exp $ */ #include @@ -48,21 +48,20 @@ static int mpls_swap(struct mbuf *, mpls_label_t); static int mpls_pop(struct mbuf *, mpls_s_t *); int -mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, - struct rtentry *rt) +mpls_output(struct mbuf *m, struct rtentry *rt) { struct sockaddr_mpls *smpls = NULL; - int error=0, i; - struct sockaddr *sa = NULL; + int error = 0, i; mpls_s_t stackempty; mpls_ttl_t ttl = 255; struct ip *ip; M_ASSERTPKTHDR(m); - KASSERT(ifp != NULL, ("mpls_output: ifp can't be NULL")); - - /* Check if we are coming from an MPLS routing table lookup */ + /* + * Check if we are coming from an MPLS routing table lookup. + * The rt_key of this rtentry will have a family AF_MPLS if so. + */ stackempty = rt_key(rt)->sa_family != AF_MPLS ? 1 : 0; if (stackempty) { switch (rt_key(rt)->sa_family) { @@ -79,13 +78,17 @@ mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, case MPLSLOP_PUSH: error = mpls_push(&m, ntohl(smpls->smpls_label), - (i==0 && dst->sa_family != AF_MPLS) ? 1 : 0, + /* + * If we are the first label push, then + * set the bottom-of-stack bit. + */ + (stackempty && i == 0) ? 1 : 0, 0, ttl); if (error) return (error); stackempty = 0; - sa = (struct sockaddr *)smpls; + m->m_flags |= M_MPLSLABELED; break; case MPLSLOP_SWAP: /* @@ -94,10 +97,10 @@ mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, */ if (stackempty) return (ENOTSUP); + KKASSERT(m->m_flags & M_MPLSLABELED); error = mpls_swap(m, ntohl(smpls->smpls_label)); if (error) return (error); - sa = (struct sockaddr *)smpls; break; case MPLSLOP_POP: /* @@ -106,12 +109,16 @@ mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, */ if (stackempty) return (ENOTSUP); - mpls_pop(m, &stackempty); - /* If not bottom label */ - if (!stackempty) - sa = (struct sockaddr *)smpls; - else - sa = dst; + KKASSERT(m->m_flags & M_MPLSLABELED); + error = mpls_pop(m, &stackempty); + if (error) + return (error); + /* + * If we are popping out the last label then + * mark the mbuf as ~M_MPLSLABELED. + */ + if (stackempty) + m->m_flags &= ~M_MPLSLABELED; break; default: /* Unknown label operation */ @@ -119,8 +126,6 @@ mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, } } - error = (*ifp->if_output)(ifp, m, sa, rt); - return (error); } @@ -128,19 +133,19 @@ mpls_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, * Returns FALSE if no further output processing required. */ boolean_t -mpls_output_process(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, - struct rtentry *rt) +mpls_output_process(struct mbuf *m, struct rtentry *rt) { int error; + /* Does this route have MPLS label operations? */ if (!(rt->rt_flags & RTF_MPLSOPS)) return TRUE; - error = mpls_output(ifp, m, - (struct sockaddr *)dst, - rt); - if (error) + error = mpls_output(m, rt); + if (error) { + m_freem(m); return FALSE; + } return TRUE; } @@ -176,9 +181,14 @@ mpls_swap(struct mbuf *m, mpls_label_t label) { mpls = mtod(m, struct mpls *); buf = ntohl(mpls->mpls_shim); - MPLS_SET_LABEL(buf, label); ttl = MPLS_TTL(buf); - MPLS_SET_TTL(buf, --ttl); /* XXX tunnel mode: uniform, pipe, short pipe */ + if (--ttl <= 0) { + /* XXX: should send icmp ttl expired. */ + mplsstat.mplss_ttlexpired++; + return (ETIMEDOUT); + } + MPLS_SET_LABEL(buf, label); + MPLS_SET_TTL(buf, ttl); /* XXX tunnel mode: uniform, pipe, short pipe */ mpls->mpls_shim = htonl(buf); return (0); diff --git a/sys/netproto/mpls/mpls_var.h b/sys/netproto/mpls/mpls_var.h index 1fc310b859..5f3142d249 100644 --- a/sys/netproto/mpls/mpls_var.h +++ b/sys/netproto/mpls/mpls_var.h @@ -28,7 +28,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/netproto/mpls/mpls_var.h,v 1.1 2008/07/07 22:02:10 nant Exp $ + * $DragonFly: src/sys/netproto/mpls/mpls_var.h,v 1.2 2008/08/05 15:11:32 nant Exp $ */ #ifndef _NETMPLS_MPLS_VAR_H_ @@ -46,6 +46,7 @@ struct mpls_stats { u_long mplss_reserved; u_long mplss_cantforward; u_long mplss_forwarded; + u_long mplss_ttlexpired; }; #ifdef _KERNEL @@ -62,12 +63,8 @@ void mpls_init(void); boolean_t mpls_lengthcheck(struct mbuf **); struct lwkt_port * mpls_mport(struct mbuf **); void mpls_input(struct mbuf *); -int mpls_output(struct ifnet *, struct mbuf *, - struct sockaddr *, - struct rtentry *); -boolean_t mpls_output_process(struct ifnet *, struct mbuf *, - struct sockaddr *, - struct rtentry *); +int mpls_output(struct mbuf *, struct rtentry *); +boolean_t mpls_output_process(struct mbuf *, struct rtentry *); #endif /* _KERNEL */ diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 89388db78a..c181adc211 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -34,7 +34,7 @@ * * @(#)mbuf.h 8.5 (Berkeley) 2/19/95 * $FreeBSD: src/sys/sys/mbuf.h,v 1.44.2.17 2003/04/15 06:15:02 silby Exp $ - * $DragonFly: src/sys/sys/mbuf.h,v 1.48 2008/05/02 07:40:32 sephe Exp $ + * $DragonFly: src/sys/sys/mbuf.h,v 1.49 2008/08/05 15:11:32 nant Exp $ */ #ifndef _SYS_MBUF_H_ @@ -205,13 +205,14 @@ struct mbuf { #define M_PHCACHE 0x8000 /* mbuf allocated from the pkt header cache */ #define M_NOTIFICATION 0x10000 /* notification event */ #define M_VLANTAG 0x20000 /* ether_vlantag is valid */ +#define M_MPLSLABELED 0x40000 /* packet is mpls labeled */ /* * Flags copied when copying m_pkthdr. */ #define M_COPYFLAGS (M_PKTHDR|M_EOR|M_PROTO1|M_PROTO1|M_PROTO2|M_PROTO3 | \ M_PROTO4|M_PROTO5|M_BCAST|M_MCAST|M_FRAG | \ - M_FIRSTFRAG|M_LASTFRAG|M_VLANTAG) + M_FIRSTFRAG|M_LASTFRAG|M_VLANTAG|M_MPLSLABELED) /* * Flags indicating hw checksum support and sw checksum requirements. -- 2.41.0