diff options
author | 2009-01-28 22:18:43 +0000 | |
---|---|---|
committer | 2009-01-28 22:18:43 +0000 | |
commit | cd776ce1c02cbf7e65143f56c8cddb99dc402fe8 (patch) | |
tree | 40e06becdb956d756d4401189f57bd4d7ff68ed3 /sys/netmpls/mpls_output.c | |
parent | synchronize synopsis and usage. (diff) | |
download | wireguard-openbsd-cd776ce1c02cbf7e65143f56c8cddb99dc402fe8.tar.xz wireguard-openbsd-cd776ce1c02cbf7e65143f56c8cddb99dc402fe8.zip |
Get rid of the ugly rtentry hack.
We can now act as edge node and allow ipv4 packets to
enter a Label Switched Path and not just forwarding
MPLS packets.
OK claudio@
Diffstat (limited to 'sys/netmpls/mpls_output.c')
-rw-r--r-- | sys/netmpls/mpls_output.c | 125 |
1 files changed, 53 insertions, 72 deletions
diff --git a/sys/netmpls/mpls_output.c b/sys/netmpls/mpls_output.c index c8f16019444..a564f28bac8 100644 --- a/sys/netmpls/mpls_output.c +++ b/sys/netmpls/mpls_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls_output.c,v 1.4 2009/01/08 12:47:45 michele Exp $ */ +/* $OpenBSD: mpls_output.c,v 1.5 2009/01/28 22:18:44 michele Exp $ */ /* * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> @@ -33,101 +33,75 @@ extern int mpls_inkloop; #define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET) #endif -void -mpls_output(struct mbuf *m) +struct mbuf * +mpls_output(struct mbuf *m, struct rtentry *rt0) { struct ifnet *ifp = m->m_pkthdr.rcvif; struct sockaddr_mpls *smpls; - struct sockaddr_mpls *newsmpls; - struct sockaddr_mpls sa_mpls, sa_outmpls; + struct sockaddr_mpls sa_mpls; struct shim_hdr *shim; - struct rtentry *rt = NULL; - u_int32_t ttl; + struct rtentry *rt = rt0; + struct rt_mpls *rt_mpls; + //u_int32_t ttl; int i; if (!mpls_enable) { m_freem(m); - return; + goto bad; } /* reset broadcast and multicast flags, this is a P2P tunnel */ m->m_flags &= ~(M_BCAST | M_MCAST); - if (m->m_len < sizeof(*shim)) - if ((m = m_pullup(m, sizeof(*shim))) == NULL) - return; - - bzero(&sa_outmpls, sizeof(sa_outmpls)); - newsmpls = &sa_outmpls; - newsmpls->smpls_family = AF_MPLS; - newsmpls->smpls_len = sizeof(*smpls); - - shim = mtod(m, struct shim_hdr *); - - /* extract TTL */ - ttl = shim->shim_label & MPLS_TTL_MASK; - for (i = 0; i < mpls_inkloop; i++) { - bzero(&sa_mpls, sizeof(sa_mpls)); - smpls = &sa_mpls; - smpls->smpls_family = AF_MPLS; - smpls->smpls_len = sizeof(*smpls); - smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK; - -#ifdef MPLS_DEBUG - printf("smpls af %d len %d in_label %d in_ifindex %d\n", - smpls->smpls_family, smpls->smpls_len, - MPLS_LABEL_GET(smpls->smpls_label), - ifp->if_index); -#endif + if (rt == NULL) { + shim = mtod(m, struct shim_hdr *); - rt = rtalloc1(smplstosa(smpls), 1, 0); + bzero(&sa_mpls, sizeof(sa_mpls)); + smpls = &sa_mpls; + smpls->smpls_family = AF_MPLS; + smpls->smpls_len = sizeof(*smpls); + smpls->smpls_label = shim->shim_label & MPLS_LABEL_MASK; - if (rt == NULL) { - /* no entry for this label */ + rt = rtalloc1(smplstosa(smpls), 1, 0); + if (rt == NULL) { + /* no entry for this label */ #ifdef MPLS_DEBUG - printf("MPLS_DEBUG: label not found\n"); + printf("MPLS_DEBUG: label not found\n"); #endif - m_freem(m); - goto done; + m_freem(m); + goto bad; + } + rt->rt_use++; } - rt->rt_use++; - smpls = satosmpls(rt_key(rt)); - newsmpls->smpls_label = rt->rt_mpls; - + rt_mpls = (struct rt_mpls *)rt->rt_llinfo; + if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) { + /* no MPLS information for this entry */ #ifdef MPLS_DEBUG - printf("route af %d len %d in_label %d in_ifindex %d\n", - smpls->smpls_family, smpls->smpls_len, - MPLS_LABEL_GET(smpls->smpls_label), - ifp->if_index); + printf("MPLS_DEBUG: no MPLS information attached\n"); #endif + m_freem(m); + goto bad; + } - switch (rt->rt_flags & (MPLS_OP_PUSH | MPLS_OP_POP | + switch (rt_mpls->mpls_operation & (MPLS_OP_PUSH | MPLS_OP_POP | MPLS_OP_SWAP)) { - case MPLS_OP_POP: - if (MPLS_BOS_ISSET(shim->shim_label)) { - /* drop to avoid loops */ - m_freem(m); - goto done; - } - - m = mpls_shim_pop(m); - break; case MPLS_OP_PUSH: - m = mpls_shim_push(m, newsmpls); + m = mpls_shim_push(m, rt_mpls); break; + case MPLS_OP_POP: case MPLS_OP_SWAP: - m = mpls_shim_swap(m, newsmpls); - break; + /* We are entring a LSP. There isn't anything to pop + or swap yet. */ default: m_freem(m); - goto done; + goto bad; } if (m == NULL) - goto done; + goto bad; /* refetch label */ shim = mtod(m, struct shim_hdr *); @@ -136,22 +110,29 @@ mpls_output(struct mbuf *m) if (ifp != NULL) break; - RTFREE(rt); + if (rt0 != rt) + RTFREE(rt); + rt = NULL; } /* write back TTL */ - shim->shim_label = (shim->shim_label & ~MPLS_TTL_MASK) | ttl; + shim->shim_label &= ~MPLS_TTL_MASK; + shim->shim_label |= MPLS_BOS_MASK | htonl(mpls_defttl); #ifdef MPLS_DEBUG - printf("MPLS: sending on %s outlabel %x dst af %d in %d out %d\n", - ifp->if_xname, ntohl(shim->shim_label), smpls->smpls_family, - MPLS_LABEL_GET(smpls->smpls_label), - MPLS_LABEL_GET(smpls->smpls_label)); + printf("MPLS: sending on %s outshim %x outlabel %d\n", + ifp->if_xname, ntohl(shim->shim_label), + MPLS_LABEL_GET(rt_mpls->mpls_label)); #endif - (*ifp->if_output)(ifp, m, smplstosa(smpls), rt); -done: - if (rt) + if (rt != rt0) RTFREE(rt); + + return (m); +bad: + if (rt != rt0) + RTFREE(rt); + + return (NULL); } |