diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-06-09 11:40:37 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2010-06-09 11:40:37 +0000 |
commit | 6f13ba21d6f7260f387090f2ae88e4948e93e2a8 (patch) | |
tree | fe821294a052a554635e5d2a114cf870a822d6b7 /sys/netmpls | |
parent | 7eb33f99019ef5fa388dbe19b943dd952ea39863 (diff) |
Fix the pop operation to make PHP work again. When popping the last label
by a pop operation we need to forward the packet to the specified nexthop
as is. This is done by calling the interface output routine directly.
This is different to the local operation since that one injects the packets
into ip_input() via netisr.
OK michele
Diffstat (limited to 'sys/netmpls')
-rw-r--r-- | sys/netmpls/mpls.h | 5 | ||||
-rw-r--r-- | sys/netmpls/mpls_input.c | 116 |
2 files changed, 77 insertions, 44 deletions
diff --git a/sys/netmpls/mpls.h b/sys/netmpls/mpls.h index 4137c98ec60..316d0f7ed86 100644 --- a/sys/netmpls/mpls.h +++ b/sys/netmpls/mpls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls.h,v 1.23 2010/06/02 15:41:06 claudio Exp $ */ +/* $OpenBSD: mpls.h,v 1.24 2010/06/09 11:40:36 claudio Exp $ */ /* * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. @@ -181,7 +181,4 @@ void mpls_input(struct mbuf *); int mpls_output(struct ifnet *, struct mbuf *, struct sockaddr *, struct rtentry *); -void mpls_ip_input(struct mbuf *, u_int8_t); -void mpls_ip6_input(struct mbuf *, u_int8_t); - #endif /* _KERNEL */ diff --git a/sys/netmpls/mpls_input.c b/sys/netmpls/mpls_input.c index bdab232a85b..9b0231a6922 100644 --- a/sys/netmpls/mpls_input.c +++ b/sys/netmpls/mpls_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls_input.c,v 1.26 2010/06/02 15:41:07 claudio Exp $ */ +/* $OpenBSD: mpls_input.c,v 1.27 2010/06/09 11:40:36 claudio Exp $ */ /* * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> @@ -56,6 +56,9 @@ extern int mpls_inkloop; extern int mpls_mapttl_ip; extern int mpls_mapttl_ip6; +int mpls_ip_adjttl(struct mbuf *, u_int8_t); +int mpls_ip6_adjttl(struct mbuf *, u_int8_t); + void mpls_init(void) { @@ -93,7 +96,7 @@ mpls_input(struct mbuf *m) struct rtentry *rt = NULL; struct rt_mpls *rt_mpls; u_int8_t ttl; - int i, hasbos; + int i, s, hasbos; if (!ISSET(ifp->if_xflags, IFXF_MPLS)) { m_freem(m); @@ -117,7 +120,7 @@ mpls_input(struct mbuf *m) ifp->if_xname, MPLS_LABEL_GET(shim->shim_label), MPLS_TTL_GET(shim->shim_label), MPLS_BOS_ISSET(shim->shim_label)); -#endif /* MPLS_DEBUG */ +#endif /* check and decrement TTL */ ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); @@ -159,13 +162,23 @@ mpls_input(struct mbuf *m) * to be at the beginning of the stack. */ if (hasbos) { - mpls_ip_input(m, ttl); + if (mpls_ip_adjttl(m, ttl)) + goto done; + s = splnet(); + IF_INPUT_ENQUEUE(&ipintrq, m); + schednetisr(NETISR_IP); + splx(s); goto done; } else continue; case MPLS_LABEL_IPV6NULL: if (hasbos) { - mpls_ip6_input(m, ttl); + if (mpls_ip6_adjttl(m, ttl)) + goto done; + s = splnet(); + IF_INPUT_ENQUEUE(&ip6intrq, m); + schednetisr(NETISR_IPV6); + splx(s); goto done; } else continue; @@ -208,20 +221,26 @@ mpls_input(struct mbuf *m) break; if (!rt->rt_gateway) { -#ifdef MPLS_DEBUG - printf("MPLS_DEBUG: no layer 3 informations " - "attached\n"); -#endif m_freem(m); goto done; } switch(rt->rt_gateway->sa_family) { case AF_INET: - mpls_ip_input(m, ttl); + if (mpls_ip_adjttl(m, ttl)) + break; + s = splnet(); + IF_INPUT_ENQUEUE(&ipintrq, m); + schednetisr(NETISR_IP); + splx(s); break; case AF_INET6: - mpls_ip6_input(m, ttl); + if (mpls_ip6_adjttl(m, ttl)) + break; + s = splnet(); + IF_INPUT_ENQUEUE(&ip6intrq, m); + schednetisr(NETISR_IPV6); + splx(s); break; default: m_freem(m); @@ -229,19 +248,45 @@ mpls_input(struct mbuf *m) goto done; case MPLS_OP_POP: m = mpls_shim_pop(m); - if (hasbos) { + if (!hasbos) + /* redo lookup with next label */ + break; + + ifp = rt->rt_ifp; #if NMPE > 0 - if (rt->rt_ifp->if_type == IFT_MPLS) { - smpls = satosmpls(rt_key(rt)); - mpe_input(m, rt->rt_ifp, smpls, ttl); - goto done; - } + if (ifp->if_type == IFT_MPLS) { + smpls = satosmpls(rt_key(rt)); + mpe_input(m, rt->rt_ifp, smpls, ttl); + goto done; + } #endif - /* last label but we have no clue so drop */ + if (!rt->rt_gateway) { m_freem(m); goto done; } - break; + + switch(rt->rt_gateway->sa_family) { + case AF_INET: + if (mpls_ip_adjttl(m, ttl)) + goto done; + break; + case AF_INET6: + if (mpls_ip6_adjttl(m, ttl)) + goto done; + break; + default: + m_freem(m); + goto done; + } + + /* Output iface is not MPLS-enabled */ + if (!ISSET(ifp->if_xflags, IFXF_MPLS)) { + m_freem(m); + goto done; + } + + (*ifp->if_ll_output)(ifp, m, rt->rt_gateway, rt); + goto done; case MPLS_OP_PUSH: m = mpls_shim_push(m, rt_mpls); break; @@ -293,27 +338,27 @@ done: RTFREE(rt); } -void -mpls_ip_input(struct mbuf *m, u_int8_t ttl) +int +mpls_ip_adjttl(struct mbuf *m, u_int8_t ttl) { struct ip *ip; - int s, hlen; + int hlen; if (mpls_mapttl_ip) { if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof(struct ip))) == NULL) - return; + return -1; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; if (m->m_len < hlen) { if ((m = m_pullup(m, hlen)) == NULL) - return; + return -1; ip = mtod(m, struct ip *); } - + /* make sure we have a valid header */ if (in_cksum(m, hlen) != 0) { m_free(m); - return; + return -1; } /* set IP ttl from MPLS ttl */ @@ -323,32 +368,23 @@ mpls_ip_input(struct mbuf *m, u_int8_t ttl) ip->ip_sum = 0; ip->ip_sum = in_cksum(m, hlen); } - - s = splnet(); - IF_INPUT_ENQUEUE(&ipintrq, m); - schednetisr(NETISR_IP); - splx(s); + return 0; } -void -mpls_ip6_input(struct mbuf *m, u_int8_t ttl) +int +mpls_ip6_adjttl(struct mbuf *m, u_int8_t ttl) { struct ip6_hdr *ip6hdr; - int s; if (mpls_mapttl_ip6) { if (m->m_len < sizeof (struct ip6_hdr) && (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) - return; + return -1; ip6hdr = mtod(m, struct ip6_hdr *); /* set IPv6 ttl from MPLS ttl */ ip6hdr->ip6_hlim = ttl; } - - s = splnet(); - IF_INPUT_ENQUEUE(&ip6intrq, m); - schednetisr(NETISR_IPV6); - splx(s); + return 0; } |