summaryrefslogtreecommitdiffstats
path: root/sys/netmpls/mpls_input.c
diff options
context:
space:
mode:
authorclaudio <claudio@openbsd.org>2010-05-28 12:09:09 +0000
committerclaudio <claudio@openbsd.org>2010-05-28 12:09:09 +0000
commit769a1fea285f19c0a9cb41f1b4606a8c59697993 (patch)
treee2f32986198aeb7045f73aa001b35f6fd14e5807 /sys/netmpls/mpls_input.c
parentAdd missing initialization. (diff)
downloadwireguard-openbsd-769a1fea285f19c0a9cb41f1b4606a8c59697993.tar.xz
wireguard-openbsd-769a1fea285f19c0a9cb41f1b4606a8c59697993.zip
Rework the way we handle MPLS in the kernel. Instead of fumbling MPLS into
ether_output() and later on other L2 output functions use a trick and over- load the ifp->if_output() function pointer on MPLS enabled interfaces to go through mpls_output() which will then call the link level output function. By setting IFXF_MPLS on an interface the output pointers are switched. This now allows to cleanup the MPLS input and output pathes and fix mpe(4) so that the MPLS code now actually works for both P and PE systems. Tested by myself and michele (A custom kernel with MPLS and mpe enabled is still needed).
Diffstat (limited to 'sys/netmpls/mpls_input.c')
-rw-r--r--sys/netmpls/mpls_input.c67
1 files changed, 38 insertions, 29 deletions
diff --git a/sys/netmpls/mpls_input.c b/sys/netmpls/mpls_input.c
index 51608cf2bb1..d4e65784b7a 100644
--- a/sys/netmpls/mpls_input.c
+++ b/sys/netmpls/mpls_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpls_input.c,v 1.22 2010/05/07 13:33:17 claudio Exp $ */
+/* $OpenBSD: mpls_input.c,v 1.23 2010/05/28 12:09:10 claudio Exp $ */
/*
* Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org>
@@ -95,7 +95,7 @@ mpls_input(struct mbuf *m)
u_int8_t ttl;
int i, hasbos;
- if (!mpls_enable) {
+ if (!mpls_enable || !ISSET(ifp->if_xflags, IFXF_MPLS)) {
m_freem(m);
return;
}
@@ -132,11 +132,11 @@ mpls_input(struct mbuf *m)
}
ttl--;
+ bzero(&sa_mpls, sizeof(sa_mpls));
+ smpls = &sa_mpls;
+ smpls->smpls_family = AF_MPLS;
+ smpls->smpls_len = sizeof(*smpls);
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
@@ -151,15 +151,13 @@ mpls_input(struct mbuf *m)
m = mpls_shim_pop(m);
shim = mtod(m, struct shim_hdr *);
- switch (ntohl(smpls->smpls_label)) {
-
+ switch (ntohl(smpls->smpls_label)) {
case MPLS_LABEL_IPV4NULL:
if (hasbos) {
mpls_ip_input(m, ttl);
goto done;
} else
continue;
-
case MPLS_LABEL_IPV6NULL:
if (hasbos) {
mpls_ip6_input(m, ttl);
@@ -184,7 +182,6 @@ mpls_input(struct mbuf *m)
}
rt->rt_use++;
- smpls = satosmpls(rt_key(rt));
rt_mpls = (struct rt_mpls *)rt->rt_llinfo;
if (rt_mpls == NULL || (rt->rt_flags & RTF_MPLS) == 0) {
@@ -196,17 +193,14 @@ mpls_input(struct mbuf *m)
goto done;
}
- if (rt_mpls->mpls_operation == MPLS_OP_LOCAL) {
+ hasbos = MPLS_BOS_ISSET(shim->shim_label);
+ switch (rt_mpls->mpls_operation) {
+ case MPLS_OP_LOCAL:
/* Packet is for us */
- hasbos = MPLS_BOS_ISSET(shim->shim_label);
- if (!hasbos) {
-#ifdef MPLS_DEBUG
- printf("MPLS_DEBUG: packet malformed\n");
-#endif
- m_freem(m);
- goto done;
- }
m = mpls_shim_pop(m);
+ if (!hasbos)
+ /* redo lookup with next label */
+ break;
if (!rt->rt_gateway) {
#ifdef MPLS_DEBUG
@@ -227,16 +221,13 @@ mpls_input(struct mbuf *m)
default:
m_freem(m);
}
-
goto done;
- }
-
- if (rt_mpls->mpls_operation & MPLS_OP_POP) {
- hasbos = MPLS_BOS_ISSET(shim->shim_label);
+ case MPLS_OP_POP:
+ m = mpls_shim_pop(m);
if (hasbos) {
- m = mpls_shim_pop(m);
#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;
}
@@ -245,13 +236,23 @@ mpls_input(struct mbuf *m)
m_freem(m);
goto done;
}
+ break;
+ case MPLS_OP_PUSH:
+ m = mpls_shim_push(m, rt_mpls);
+ break;
+ case MPLS_OP_SWAP:
+ m = mpls_shim_swap(m, rt_mpls);
+ break;
}
+ if (m == NULL)
+ goto done;
+
/* refetch label */
shim = mtod(m, struct shim_hdr *);
- ifp = rt->rt_ifp;
- if (ifp != NULL)
+ ifp = rt->rt_ifp;
+ if (ifp != NULL && rt_mpls->mpls_operation != MPLS_OP_LOCAL)
break;
RTFREE(rt);
@@ -273,14 +274,22 @@ mpls_input(struct mbuf *m)
MPLS_LABEL_GET(rt_mpls->mpls_label));
#endif
- (*ifp->if_output)(ifp, m, smplstosa(smpls), rt);
+ /* Output iface is not MPLS-enabled */
+ if (!ISSET(ifp->if_xflags, IFXF_MPLS)) {
+#ifdef MPLS_DEBUG
+ printf("MPLS_DEBUG: interface not mpls enabled\n");
+#endif
+ goto done;
+ }
+
+ (*ifp->if_ll_output)(ifp, m, smplstosa(smpls), rt);
done:
if (rt)
RTFREE(rt);
}
void
-mpls_ip_input(struct mbuf *m, u_int8_t ttl)
+mpls_ip_input(struct mbuf *m, u_int8_t ttl)
{
struct ip *ip;
int s, hlen;