diff options
author | Michele Marchetto <michele@cvs.openbsd.org> | 2009-01-28 22:18:45 +0000 |
---|---|---|
committer | Michele Marchetto <michele@cvs.openbsd.org> | 2009-01-28 22:18:45 +0000 |
commit | 7227a1f7a8d21a364dce2ce2e513c4e0826f0655 (patch) | |
tree | 53b778afc500a2b1c3a9d76a056b3dad0f2ef05a /sys/netmpls | |
parent | cc411b2e1c4c556ba9e319f50cf1c1422f56db9d (diff) |
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')
-rw-r--r-- | sys/netmpls/mpls.h | 22 | ||||
-rw-r--r-- | sys/netmpls/mpls_input.c | 35 | ||||
-rw-r--r-- | sys/netmpls/mpls_output.c | 125 | ||||
-rw-r--r-- | sys/netmpls/mpls_shim.c | 18 |
4 files changed, 98 insertions, 102 deletions
diff --git a/sys/netmpls/mpls.h b/sys/netmpls/mpls.h index f89151248bb..df287182ee5 100644 --- a/sys/netmpls/mpls.h +++ b/sys/netmpls/mpls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls.h,v 1.16 2009/01/08 12:47:45 michele Exp $ */ +/* $OpenBSD: mpls.h,v 1.17 2009/01/28 22:18:44 michele Exp $ */ /* * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. @@ -94,9 +94,15 @@ struct sockaddr_mpls { u_int32_t smpls_pad1[2]; }; -#define MPLS_OP_POP RTF_PROTO1 +struct rt_mpls { + u_int32_t mpls_label; + u_int8_t mpls_operation; + u_int8_t mpls_exp; +}; + +#define MPLS_OP_POP RTF_PROTO3 #define MPLS_OP_PUSH RTF_PROTO2 -#define MPLS_OP_SWAP RTF_PROTO3 +#define MPLS_OP_SWAP RTF_PROTO1 #define MPLS_INKERNEL_LOOP_MAX 16 @@ -167,11 +173,11 @@ void mpls_init(void); void mplsintr(void); struct mbuf *mpls_shim_pop(struct mbuf *); -struct mbuf *mpls_shim_swap(struct mbuf *, struct sockaddr_mpls *); -struct mbuf *mpls_shim_push(struct mbuf *, struct sockaddr_mpls *); +struct mbuf *mpls_shim_swap(struct mbuf *, struct rt_mpls *); +struct mbuf *mpls_shim_push(struct mbuf *, struct rt_mpls *); -int mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t); -void mpls_input(struct mbuf *); -void mpls_output(struct mbuf *); +int mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t); +void mpls_input(struct mbuf *); +struct mbuf *mpls_output(struct mbuf *, struct rtentry *); #endif /* _KERNEL */ diff --git a/sys/netmpls/mpls_input.c b/sys/netmpls/mpls_input.c index 9382aa6f9cb..bd7d2a28d62 100644 --- a/sys/netmpls/mpls_input.c +++ b/sys/netmpls/mpls_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls_input.c,v 1.17 2009/01/08 12:47:45 michele Exp $ */ +/* $OpenBSD: mpls_input.c,v 1.18 2009/01/28 22:18:44 michele Exp $ */ /* * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org> @@ -70,10 +70,10 @@ mpls_input(struct mbuf *m) { 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; + struct rt_mpls *rt_mpls; u_int8_t ttl; int i, hasbos; @@ -92,11 +92,6 @@ mpls_input(struct mbuf *m) 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 *); #ifdef MPLS_DEBUG @@ -171,9 +166,18 @@ mpls_input(struct mbuf *m) 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("MPLS_DEBUG: no MPLS information attached\n"); +#endif + m_freem(m); + goto done; + } - 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: @@ -192,10 +196,10 @@ mpls_input(struct mbuf *m) } break; case MPLS_OP_PUSH: - m = mpls_shim_push(m, newsmpls); + m = mpls_shim_push(m, rt_mpls); break; case MPLS_OP_SWAP: - m = mpls_shim_swap(m, newsmpls); + m = mpls_shim_swap(m, rt_mpls); break; default: m_freem(m); @@ -216,6 +220,11 @@ mpls_input(struct mbuf *m) rt = NULL; } + if (rt == NULL) { + m_freem(m); + goto done; + } + /* write back TTL */ shim->shim_label = (shim->shim_label & ~MPLS_TTL_MASK) | htonl(ttl); @@ -223,7 +232,7 @@ mpls_input(struct mbuf *m) 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(newsmpls->smpls_label)); + MPLS_LABEL_GET(rt_mpls->mpls_label)); #endif (*ifp->if_output)(ifp, m, smplstosa(smpls), rt); 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); } diff --git a/sys/netmpls/mpls_shim.c b/sys/netmpls/mpls_shim.c index 32c27713236..3abe64feb8b 100644 --- a/sys/netmpls/mpls_shim.c +++ b/sys/netmpls/mpls_shim.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpls_shim.c,v 1.5 2009/01/08 12:47:45 michele Exp $ */ +/* $OpenBSD: mpls_shim.c,v 1.6 2009/01/28 22:18:44 michele Exp $ */ /* * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. @@ -50,7 +50,7 @@ mpls_shim_pop(struct mbuf *m) /* catch-up next shim_hdr */ if (m->m_len < sizeof(struct shim_hdr)) - if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == NULL) return (NULL); /* return mbuf */ @@ -58,26 +58,26 @@ mpls_shim_pop(struct mbuf *m) } struct mbuf * -mpls_shim_swap(struct mbuf *m, struct sockaddr_mpls *smplsp) +mpls_shim_swap(struct mbuf *m, struct rt_mpls *rt_mpls) { struct shim_hdr *shim; /* pullup shim_hdr */ if (m->m_len < sizeof(struct shim_hdr)) - if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == NULL) return (NULL); shim = mtod(m, struct shim_hdr *); /* swap label */ shim->shim_label &= ~MPLS_LABEL_MASK; - shim->shim_label |= smplsp->smpls_label & MPLS_LABEL_MASK; + shim->shim_label |= rt_mpls->mpls_label & MPLS_LABEL_MASK; /* swap exp : XXX exp override */ { u_int32_t t; shim->shim_label &= ~MPLS_EXP_MASK; - t = 0; + t = rt_mpls->mpls_exp << MPLS_EXP_OFFSET; shim->shim_label |= htonl(t) & MPLS_EXP_MASK; } @@ -85,16 +85,16 @@ mpls_shim_swap(struct mbuf *m, struct sockaddr_mpls *smplsp) } struct mbuf * -mpls_shim_push(struct mbuf *m, struct sockaddr_mpls *smplsp) +mpls_shim_push(struct mbuf *m, struct rt_mpls *rt_mpls) { struct shim_hdr *shim; M_PREPEND(m, sizeof(struct shim_hdr), M_DONTWAIT); - if (m == 0) + if (m == NULL) return (NULL); shim = mtod(m, struct shim_hdr *); bzero((caddr_t)shim, sizeof(*shim)); - return (mpls_shim_swap(m, smplsp)); + return (mpls_shim_swap(m, rt_mpls)); } |