Date: Tue, 8 Jul 2008 01:27:58 GMT From: Ryan French <rfrench@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 144854 for review Message-ID: <200807080127.m681Rw2a047709@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=144854 Change 144854 by rfrench@rfrench_mpls on 2008/07/08 01:27:50 Initial import from OpenBSDs currently 'in progress' implementation of MPLS, which is based on the original AYAME project for NetBSD. I havent tested it to make sure it works yet. Affected files ... .. //depot/projects/soc2008/rfrench_mpls/netmpls/mpls.h#2 edit .. //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_input.c#2 edit .. //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_proto.c#2 edit .. //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_raw.c#2 edit .. //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_shim.c#2 edit Differences ... ==== //depot/projects/soc2008/rfrench_mpls/netmpls/mpls.h#2 (text+ko) ==== @@ -1,1 +1,173 @@ - + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULARPURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, ORCONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NETMPLS_MPLS_H_ +#define _NETMPLS_MPLS_H_ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/queue.h> + +#include <net/if.h> +#include <net/if_dl.h> + +/* + * Structure of a SHIM header. + */ +#define MPLS_LABEL_MAX ((1 << 20) - 1) + +struct shim_hdr { + u_int32_t shim_label; /* 20 bit label, 4 bit exp & BoS, 8 bit TTL */ +}; + +/* + * By byte-swapping the constants, we avoid ever having to byte-swap IP + * addresses inside the kernel. Unfortunately, user-level programs rely + * on these macros not doing byte-swapping. + */ + +#ifdef _KERNEL +#define __MADDR(x) ((u_int32_t)htonl((u_int32_t)(x))) +#else +#define __MADDR(x) ((u_int32_t)(x)) +#endif + +#define MPLS_LABEL_MASK __MADDR(0xfffff000U) +#define MPLS_LABEL_OFFSET 12 +#define MPLS_EXP_MASK __MADDR(0x00000e00U) +#define MPLS_EXP_OFFSET 9 +#define MPLS_BOS_MASK __MADDR(0x00000100U) +#define MPLS_BOS_OFFSET 8 +#define MPLS_TTL_MASK __MADDR(0x000000ffU) + +#define MPLS_BOS_ISSET(l) (((l) & MPLS_BOS_MASK) == MPLS_BOS_MASK) + +/* Reserved lavel values (RFC3032) */ +#define MPLS_LABEL_IPV4NULL 0 /* IPv4 Explicit NULL Label */ +#define MPLS_LABEL_RTALERT 1 /* Router Alert Label */ +#define MPLS_LABEL_IPV6NULL 2 /* IPv6 Explicit NULL Label */ +#define MPLS_LABEL_IMPLNULL 3 /* Implicit NULL Label */ +/* MPLS_LABEL_RESERVED 4-15 */ /* Values 4-15 are reserved */ +#define MPLS_LABEL_RESERVED_MAX 15 + +/* + * Socket address + */ + +struct sockaddr_mpls { + u_int8_t smpls_len; /* length */ + u_int8_t smpls_family; /* AF_MPLS */ + u_int8_t smpls_operation; + u_int8_t smpls_out_exp; /* outgoing exp value */ + u_int32_t smpls_out_label; /* outgoing MPLS label */ + u_int16_t smpls_out_ifindex; + u_int16_t smpls_in_ifindex; + u_int32_t smpls_in_label; /* MPLS label 20 bits*/ +#if MPLS_MCAST + u_int8_t smpls_mcexp; + u_int8_t smpls_pad2[2]; + u_int32_t smpls_mclabel; +#endif +}; + +#define MPLS_OP_POP 1 +#define MPLS_OP_PUSH 2 +#define MPLS_OP_SWAP 3 + +#define MPLS_INKERNEL_LOOP_MAX 16 + +#define satosmpls(sa) ((struct sockaddr_mpls *)(sa)) +#define smplstosa(smpls) ((struct sockaddr *)(smpls)) + +/* + * Names for MPLS sysctl objects + */ +#define MPLSCTL_ENABLE 1 +#define MPLSCTL_DEFTTL 2 +#define MPLSCTL_IFQUEUE 3 +#define MPLSCTL_MAXINKLOOP 4 +#define MPLSCTL_MAXID 5 + +#define MPLSCTL_NAMES { \ + { 0, 0 }, \ + { "enable", CTLTYPE_INT }, \ + { "ttl", CTLTYPE_INT }, \ + { "ifq", CTLTYPE_NODE },\ + { "maxloop_inkernel", CTLTYPE_INT }, \ +} + +#define MPLSCTL_VARS { \ + 0, \ + &mpls_enable, \ + &mpls_defttl, \ + 0, \ + &mpls_inkloop, \ +} + +#endif + +#ifdef _KERNEL + +struct mpe_softc { + struct ifnet sc_if; /* the interface */ + int sc_unit; + struct shim_hdr sc_shim; + LIST_ENTRY(mpe_softc) sc_list; +}; + +#define MPE_HDRLEN sizeof(struct shim_hdr) +#define MPE_MTU 1500 +#define MPE_MTU_MIN 256 +#define MPE_MTU_MAX 8192 + +void mpe_input(struct mbuf *, struct ifnet *, struct sockaddr_mpls *, + u_int32_t); + +extern int mpls_raw_usrreq(struct socket *, int, struct mbuf *, + struct mbuf *, struct mbuf *, struct proc *); + +extern struct ifqueue mplsintrq; /* MPLS input queue */ +extern int mplsqmaxlen; /* MPLS input queue length */ +extern int mpls_enable; +extern int mpls_defttl; + +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 *); + +int mpls_sysctl(int *, u_int, void *, size_t *, void *, size_t); +void mpls_input(struct mbuf *); + +#endif /* _KERNEL */ ==== //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_input.c#2 (text+ko) ==== @@ -1,23 +1,209 @@ -#include <sys/cdefs.h> + +/* + * Copyright (c) 2008 Claudio Jeker <claudio@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 "mpe.h" #include <sys/param.h> +#include <sys/mbuf.h> #include <sys/systm.h> -#include <sys/callout.h> -#include <sys/mbuf.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +struct ifqueue mplsintrq; +int mplsqmaxlen = IFQ_MAXLEN; +extern int mpls_inkloop; -#include <net/netisr.h> +#ifdef MPLS_DEBUG +#define MPLS_LABEL_GET(l) ((ntohl((l) & MPLS_LABEL_MASK)) >> MPLS_LABEL_OFFSET) +#define MPLS_TTL_GET(l) (ntohl((l) & MPLS_TTL_MASK)) +#endif -struct ifqueue mplsintrq; +void +mpls_init(void) +{ + mplsintrq.ifq_maxlen = mplsqmaxlen; +} void -mpls_init() +mplsintr(void) { - printf("MPLS packet received, netisr_register called"); - netisr_register(NETISR_MPLS, mpls_input, &mplsintrq, NETISR_MPSAFE); -} + struct mbuf *m; + int s; + + for (;;) { + /* Get next datagram of input queue */ + s = splnet(); + IF_DEQUEUE(&mplsintrq, m); + splx(s); + if (m == NULL) + return; +#ifdef DIAGNOSTIC + if ((m->m_flags & M_PKTHDR) == 0) + panic("ipintr no HDR"); +#endif + mpls_input(m); + } +} void mpls_input(struct mbuf *m) { - printf("MPLS input called"); -} + 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, hasbos; + + if (!mpls_enable) { + m_freem(m); + return; + } + + /* drop all broadcast and multicast packets */ + if (m->m_flags & (M_BCAST | M_MCAST)) { + m_freem(m); + return; + } + + if (m->m_len < sizeof(*shim)) + if ((m = m_pullup(m, sizeof(*shim))) == NULL) + return; + + shim = mtod(m, struct shim_hdr *); + +#ifdef MPLS_DEBUG + printf("mpls_input: iface %s label=%d, ttl=%d BoS %d\n", + ifp->if_xname, MPLS_LABEL_GET(shim->shim_label), + MPLS_TTL_GET(shim->shim_label), + MPLS_BOS_ISSET(shim->shim_label)); +#endif /* MPLS_DEBUG */ + + /* check and decrement TTL */ + ttl = ntohl(shim->shim_label & MPLS_TTL_MASK); + if (ttl <= 1) { + /* TTL exceeded */ + /* + * XXX if possible hand packet up to network layer so that an + * ICMP TTL exceeded can be sent back. + */ + m_freem(m); + return; + } + ttl = htonl(ttl - 1); + + 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: + hasbos = MPLS_BOS_ISSET(shim->shim_label); + m = mpls_shim_pop(m); + if (hasbos) { +#if NMPE > 0 + if (rt->rt_ifp->if_type == IFT_MPLS) { + mpe_input(m, rt->rt_ifp, smpls, ttl); + goto done; + } +#endif + /* last label but we have no clue so drop */ + m_freem(m); + goto done; + } + 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); +} ==== //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_proto.c#2 (text+ko) ==== @@ -1,1 +1,74 @@ - + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/protosw.h> +#include <sys/domain.h> +#include <sys/mbuf.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +/* + * MPLS protocol family: + */ + +extern struct domain mplsdomain; + +struct protosw mplssw[] = { +{ 0, &mplsdomain, 0, 0, + 0, 0, 0, 0, + 0, + mpls_init, 0, 0, 0, mpls_sysctl +}, +{ SOCK_DGRAM, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, + 0, 0, 0, 0, + mpls_raw_usrreq, + 0, 0, 0, 0, mpls_sysctl, +}, +/* raw wildcard */ +{ SOCK_RAW, &mplsdomain, 0, PR_ATOMIC|PR_ADDR, + 0, 0, 0, 0, + mpls_raw_usrreq, + 0, 0, 0, 0, mpls_sysctl, +}, +}; + +struct domain mplsdomain = { + AF_MPLS, "mpls", mpls_init, 0, 0, + mplssw, + &mplssw[sizeof(mplssw)/sizeof(mplssw[0])], 0, + rn_inithead, + offsetof(struct sockaddr_mpls, smpls_in_ifindex) << 3, + sizeof(struct sockaddr_mpls) +}; ==== //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_raw.c#2 (text+ko) ==== @@ -1,1 +1,145 @@ - + +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/sockio.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +#define MPLS_RAW_SNDQ 8192 +#define MPLS_RAW_RCVQ 8192 + +u_long mpls_raw_sendspace = MPLS_RAW_SNDQ; +u_long mpls_raw_recvspace = MPLS_RAW_RCVQ; + +int mpls_enable = 0; +int mpls_defttl = 255; +int mpls_inkloop = 16; +int mpls_push_expnull_ip = 0; +int mpls_push_expnull_ip6 = 0; +int mpls_mapttl_ip = 1; +int mpls_mapttl_ip6 = 0; + +int *mplsctl_vars[MPLSCTL_MAXID] = MPLSCTL_VARS; + +int mpls_control(struct socket *, u_long, caddr_t, struct ifnet *); + +/* + * Generic MPLS control operations (ioctl's). + * Ifp is 0 if not an interface-specific ioctl. + */ +/* ARGSUSED */ +int +mpls_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp) +{ + return (EOPNOTSUPP); +} + +int +mpls_raw_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, + struct mbuf *control, struct proc *p) +{ + int error = 0; + +#ifdef MPLS_DEBUG + printf("mpls_raw_usrreq: called! (reqid=%d).\n", req); +#endif /* MPLS_DEBUG */ + + if (req == PRU_CONTROL) + return (mpls_control(so, (u_long)m, (caddr_t)nam, + (struct ifnet *)control)); + + switch (req) { + case PRU_ATTACH: + if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { + error = soreserve(so, mpls_raw_sendspace, + mpls_raw_recvspace); + if (error) + break; + } + break; + + case PRU_DETACH: + case PRU_BIND: + case PRU_LISTEN: + case PRU_CONNECT: + case PRU_CONNECT2: + case PRU_DISCONNECT: + case PRU_SHUTDOWN: + case PRU_RCVD: + case PRU_SEND: + case PRU_SENSE: + case PRU_RCVOOB: + case PRU_SENDOOB: + case PRU_SOCKADDR: + case PRU_PEERADDR: + error = EOPNOTSUPP; + break; + + default: + panic("rip_usrreq"); + } + + return (error); +} + +int +mpls_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) +{ + if (name[0] >= MPLSCTL_MAXID) + return EOPNOTSUPP; + + /* Almost all sysctl names at this level are terminal. */ + if (namelen != 1 && name[0] != MPLSCTL_IFQUEUE) + return (ENOTDIR); + + switch (name[0]) { + case MPLSCTL_IFQUEUE: + return (sysctl_ifq(name + 1, namelen - 1, + oldp, oldlenp, newp, newlen, &mplsintrq)); + default: + return sysctl_int_arr(mplsctl_vars, name, namelen, + oldp, oldlenp, newp, newlen); + } +} ==== //depot/projects/soc2008/rfrench_mpls/netmpls/mpls_shim.c#2 (text+ko) ==== @@ -1,1 +1,99 @@ +/* + * Copyright (C) 1999, 2000 and 2001 AYAME Project, WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/route.h> + +#include <netmpls/mpls.h> + +struct mbuf * +mpls_shim_pop(struct mbuf *m) +{ + /* shaves off top shim header from mbuf */ + m_adj(m, sizeof(struct shim_hdr)); + + /* catch-up next shim_hdr */ + if (m->m_len < sizeof(struct shim_hdr)) + if ((m = m_pullup(m, sizeof(struct shim_hdr))) == 0) + return (NULL); + + /* return mbuf */ + return (m); +} + +struct mbuf * +mpls_shim_swap(struct mbuf *m, struct sockaddr_mpls *smplsp) +{ + 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) + return (NULL); + shim = mtod(m, struct shim_hdr *); + + /* swap label */ + shim->shim_label &= ~MPLS_LABEL_MASK; + shim->shim_label |= smplsp->smpls_out_label & MPLS_LABEL_MASK; + + /* swap exp : XXX exp override */ + { + u_int32_t t; + + shim->shim_label &= ~MPLS_EXP_MASK; + t = smplsp->smpls_out_exp << MPLS_EXP_OFFSET; + shim->shim_label |= htonl(t) & MPLS_EXP_MASK; + } + + return (m); +} + +struct mbuf * +mpls_shim_push(struct mbuf *m, struct sockaddr_mpls *smplsp) +{ + struct shim_hdr *shim; + + M_PREPEND(m, sizeof(struct shim_hdr), M_DONTWAIT); + if (m == 0) + return (NULL); + + shim = mtod(m, struct shim_hdr *); + bzero((caddr_t)shim, sizeof(*shim)); + + return (mpls_shim_swap(m, smplsp)); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200807080127.m681Rw2a047709>