summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_mpe.c10
-rw-r--r--sys/netmpls/mpls.h3
-rw-r--r--sys/netmpls/mpls_output.c153
3 files changed, 157 insertions, 9 deletions
diff --git a/sys/net/if_mpe.c b/sys/net/if_mpe.c
index 518220355d2..20f21292570 100644
--- a/sys/net/if_mpe.c
+++ b/sys/net/if_mpe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_mpe.c,v 1.11 2008/10/18 12:30:40 michele Exp $ */
+/* $OpenBSD: if_mpe.c,v 1.12 2008/10/28 01:16:14 michele Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@spootnik.org>
@@ -165,7 +165,7 @@ mpestart(struct ifnet *ifp)
continue;
}
m->m_pkthdr.rcvif = ifp;
- mpls_input(m);
+ mpls_output(m);
}
}
@@ -289,9 +289,6 @@ mpe_input(struct mbuf *m, struct ifnet *ifp, struct sockaddr_mpls *smpls,
bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
#endif
s = splnet();
- /*
- * assume we only get fed ipv4 packets for now.
- */
IF_ENQUEUE(&ipintrq, m);
schednetisr(NETISR_IP);
splx(s);
@@ -311,9 +308,6 @@ mpe_input6(struct mbuf *m, struct ifnet *ifp, struct sockaddr_mpls *smpls,
bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
#endif
s = splnet();
- /*
- * assume we only get fed ipv4 packets for now.
- */
IF_ENQUEUE(&ip6intrq, m);
schednetisr(NETISR_IPV6);
splx(s);
diff --git a/sys/netmpls/mpls.h b/sys/netmpls/mpls.h
index 0ad5fe11457..7b4b464d642 100644
--- a/sys/netmpls/mpls.h
+++ b/sys/netmpls/mpls.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpls.h,v 1.12 2008/10/14 20:43:33 michele Exp $ */
+/* $OpenBSD: mpls.h,v 1.13 2008/10/28 01:16:14 michele Exp $ */
/*
* Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project.
@@ -172,5 +172,6 @@ struct mbuf *mpls_shim_push(struct mbuf *, struct sockaddr_mpls *);
int mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t);
void mpls_input(struct mbuf *);
+void mpls_output(struct mbuf *);
#endif /* _KERNEL */
diff --git a/sys/netmpls/mpls_output.c b/sys/netmpls/mpls_output.c
new file mode 100644
index 00000000000..3139918be0d
--- /dev/null
+++ b/sys/netmpls/mpls_output.c
@@ -0,0 +1,153 @@
+/* $Id: mpls_output.c,v 1.1 2008/10/28 01:16:14 michele Exp $ */
+
+/*
+ * Copyright (c) 2008 Claudio Jeker <claudio@openbsd.org>
+ * Copyright (c) 2008 Michele Marchetto <michele@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netmpls/mpls.h>
+
+extern int mpls_inkloop;
+
+#ifdef MPLS_DEBUG
+#define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET)
+#endif
+
+void
+mpls_output(struct mbuf *m)
+{
+ struct ifnet *ifp = m->m_pkthdr.rcvif;
+ struct sockaddr_mpls *smpls;
+ struct sockaddr_mpls sa_mpls;
+ struct shim_hdr *shim;
+ struct rtentry *rt = NULL;
+ u_int32_t ttl;
+ int i;
+
+ if (!mpls_enable) {
+ m_freem(m);
+ return;
+ }
+
+ /* 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;
+
+ 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_in_ifindex = ifp->if_index;
+ smpls->smpls_in_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_in_label),
+ smpls->smpls_in_ifindex);
+#endif
+
+ rt = rtalloc1(smplstosa(smpls), 1, 0);
+
+ if (rt == NULL) {
+ /* no entry for this label */
+#ifdef MPLS_DEBUG
+ printf("MPLS_DEBUG: label not found\n");
+#endif
+ m_freem(m);
+ goto done;
+ }
+
+ rt->rt_use++;
+ smpls = satosmpls(rt_key(rt));
+
+#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_in_label),
+ smpls->smpls_in_ifindex);
+ printf("\top %d out_label %d out_ifindex %d\n",
+ smpls->smpls_operation,
+ MPLS_LABEL_GET(smpls->smpls_out_label),
+ smpls->smpls_out_ifindex);
+#endif
+
+ switch (smpls->smpls_operation) {
+ 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, smpls);
+ break;
+ case MPLS_OP_SWAP:
+ m = mpls_shim_swap(m, smpls);
+ break;
+ default:
+ m_freem(m);
+ goto done;
+ }
+
+ if (m == NULL)
+ goto done;
+
+ /* refetch label */
+ shim = mtod(m, struct shim_hdr *);
+ ifp = rt->rt_ifp;
+
+ if (smpls->smpls_out_ifindex)
+ break;
+
+ RTFREE(rt);
+ rt = NULL;
+ }
+
+ /* write back TTL */
+ shim->shim_label = (shim->shim_label & ~MPLS_TTL_MASK) | ttl;
+
+#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_in_label),
+ MPLS_LABEL_GET(smpls->smpls_out_label));
+#endif
+
+ (*ifp->if_output)(ifp, m, smplstosa(smpls), rt);
+done:
+ if (rt)
+ RTFREE(rt);
+}