summaryrefslogtreecommitdiff
path: root/sys/netmpls
diff options
context:
space:
mode:
authorMichele Marchetto <michele@cvs.openbsd.org>2009-01-28 22:18:45 +0000
committerMichele Marchetto <michele@cvs.openbsd.org>2009-01-28 22:18:45 +0000
commit7227a1f7a8d21a364dce2ce2e513c4e0826f0655 (patch)
tree53b778afc500a2b1c3a9d76a056b3dad0f2ef05a /sys/netmpls
parentcc411b2e1c4c556ba9e319f50cf1c1422f56db9d (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.h22
-rw-r--r--sys/netmpls/mpls_input.c35
-rw-r--r--sys/netmpls/mpls_output.c125
-rw-r--r--sys/netmpls/mpls_shim.c18
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));
}