diff options
author | 2008-10-28 01:16:14 +0000 | |
---|---|---|
committer | 2008-10-28 01:16:14 +0000 | |
commit | bf64af94e691781de678f955a0dd93173c3c979c (patch) | |
tree | 09b203c912208de481ba2ae0f3854b3303ad241e /sys/netmpls/mpls_output.c | |
parent | Try to use ACPI a little bit harder. Skip it only if ncpu < 2 and the (diff) | |
download | wireguard-openbsd-bf64af94e691781de678f955a0dd93173c3c979c.tar.xz wireguard-openbsd-bf64af94e691781de678f955a0dd93173c3c979c.zip |
Added mpls_output() used to output mpls packets originating from local host.
Strictly similar to mpls_input().
Input and OK claudio@, OK laurent@
Diffstat (limited to 'sys/netmpls/mpls_output.c')
-rw-r--r-- | sys/netmpls/mpls_output.c | 153 |
1 files changed, 153 insertions, 0 deletions
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); +} |