diff options
Diffstat (limited to 'sys/netmpls/mpls_lse.c')
-rw-r--r-- | sys/netmpls/mpls_lse.c | 333 |
1 files changed, 333 insertions, 0 deletions
diff --git a/sys/netmpls/mpls_lse.c b/sys/netmpls/mpls_lse.c new file mode 100644 index 00000000000..92ec6386d37 --- /dev/null +++ b/sys/netmpls/mpls_lse.c @@ -0,0 +1,333 @@ +/* + * 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. + */ + +/* + * + * $Id: mpls_lse.c,v 1.1 2008/04/23 11:00:35 norby Exp $ + */ + +#include <sys/param.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/errno.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/systm.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/route.h> + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +/* + * MPLS Label Switching Engine. + */ + +/* + * Process a received MPLS packet; + * the packet is in the mbuf chain m from mpls_{ether,...}. + */ +int +mpls_lse(struct ifnet *ifp, struct mbuf *m, struct sockaddr_mpls *dst, + u_int8_t bosf) +{ + struct route mplsroute; + struct route *ro = &mplsroute; + struct sockaddr_mpls *rodst = satosmpls(&mplsroute.ro_dst); /* Actual labeland stuff */ + struct rtentry *rt = NULL; + struct sockaddr_mpls *dstnew; + struct sockaddr_mpls smpls; /* XXX adhoc XXX */ + u_int8_t exp_bits; /* XXX adhoc XXX */ + int ink_loop, error = 0, bad = 0; + + bzero((caddr_t)ro, sizeof(*ro)); + bcopy((caddr_t)dst, (caddr_t)rodst, dst->smpls_len); + +/* XXX: Kefren: I don't understand this inkloop so I've replaced it with asingle + loop for easy break */ + for (ink_loop = 0; ink_loop < mpls_inkloop; ink_loop++) { +/* for (ink_loop = 0; ink_loop < 1; ink_loop++) { */ + +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d). [label=%d]\n", + __FILE__, __LINE__, ntohl(rodst->smpls_in_label)); +#endif /* MPLS_DEBUG */ + + /* + * OPERATIONS for Reserved Labels + */ + if (ntohl(rodst->smpls_in_label) <= MPLS_LABEL_RESERVED_MAX) { + printf("MPLS_DEBUG: %s(%d). [bosf = %d label = %s]\n", + __FILE__, __LINE__, bosf, + ntohl(rodst->smpls_in_label)); + switch (ntohl(rodst->smpls_in_label)) { +#ifdef INET + case MPLS_LABEL_IPV4NULL: +#if 0 /* claudio@ */ + if (bosf) { + error = mpls_ip_input(m); + goto done; + } +#endif +#ifdef MPLS_DEBUG +#endif /* MPLS_DEBUG */ + break; +#endif /* INET */ +#ifdef INET6 + case MPLS_LABEL_IPV6NULL: +#if 0 /* claudio@ */ + if (bosf) { + error = mpls_ip6_input(m); + goto done; + } +#endif + break; +#endif /* INET6 */ + } + + /* label is reserved, */ + /* but operation is unsupported or invalid */ + error = EINVAL; + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); + bad = 1; + break; + } /* MPLS RESERVED label */ + + /* + * switch packet + * + * XXX: no really, this is fun. AYAME sucks so much. */ + exp_bits = rodst->smpls_out_exp; + rodst->smpls_out_exp = 0; + + rtalloc(ro); + rt = ro->ro_rt; + bzero((caddr_t)ro, sizeof(*ro)); + + if (rt == 0) { + /* no entry for this label (silent discard) */ + /* as the scope_id you use is not set interface, etc. */ + /* error = EHOSTUNREACH; */ + error = 0; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + break; + } + + /* + if ((mtu = rt->rt_rmx.rmx_mtu) == 0) + mtu = ifp->if_mtu; + */ + + + /* + * label operations + */ + rt->rt_use++; + if (rt->rt_flags & RTF_GATEWAY) /* XXX */ + dstnew = satosmpls(rt->rt_gateway); + else { + /* XXX silent discard XXX */ + /* error = EHOSTUNREACH; */ + error = 0; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + break; + } + +#ifdef MPLS_MCAST + printf("MPLS_MCAST label=%d mclabel=%d\n", + ntohl(dstnew->smpls_in_label) & 0x000fffff, + ntohl(dstnew->smpls_mclabel)); + /* + * if gw_entry have next mplsmc entry, + * call mpls_lse again. + */ + if (dstnew->smpls_mclabel != 0) { + struct sockaddr_mpls smpmpls; + struct mbuf *nm; + memset(&smpmpls, 0, sizeof(smpmpls)); + smpmpls.smpls_len = sizeof(smpmpls); + smpmpls.smpls_family = AF_MPLS; + smpmpls.smpls_in_label = dstnew->smpls_mclabel; +#ifdef MPLS_DEBUG + printf("MPLS_MCAST label=%d mclabel=%d\n", + ntohl(dstnew->smpls_in_label) & 0x000fffff, + ntohl(dstnew->smpls_mclabel)); +#endif /* MPLS_DEBUG */ + nm = m_copym(m, 0, M_COPYALL, M_DONTWAIT); + if (nm != NULL) { +#ifdef MPLS_DEBUG + printf("MPLS_MCAST dup\n"); +#endif /* MPLS_DEBUG */ + mpls_lse(ifp, nm, &smpmpls, bosf); + m_freem(nm); + } + } +#endif /* MPLS_MCAST */ + + if (dstnew->smpls_family != AF_MPLS) { + if (bosf) { + /* send to L3? */ + switch (dstnew->smpls_family) { +#if 0 /* claudio@ */ +#ifdef INET + case AF_INET: + error = mpls_ip_input(m); + goto done; +#endif /* INET */ +#ifdef INET6 + case AF_INET6: + error = mpls_ip6_input(m); + goto done; +#endif /* INET6 */ +#endif + default: + error = EAFNOSUPPORT; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + } + break; + } else { + /* XXX */ + error = EINVAL; +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d).\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + bad = 1; + break; + } + } + + /* XXX */ + smpls = *dstnew; + smpls.smpls_out_exp = exp_bits; + dstnew = &smpls; + /* XXX Kefren */ +/* dstnew->smpls_exp = exp_bits;*/ + + switch(dstnew->smpls_operation) { + + case MPLS_OP_POP: /* Label Pop */ + + /* check bos flag */ +#if 0 /* claudio@ */ + if (bosf) { + /* + * XXXXX No ExpNULL XXXXX + * + * I can't know which l3 I shuld send to!! + * now, send to IPv4 stack (XXXXX) + * We have to 'look' into the packet + * and clasify it + * + * error = EINVAL; + * goto bad; + */ + + error = mpls_ip_input(m); + goto done; + } +#endif + /* label pop */ + if ((m = mpls_shim_pop(m, rodst, NULL, &bosf, NULL)) == 0) { + error = ENOBUFS; + goto done; + } + + break; + + case MPLS_OP_PUSH: /* Label Push */ + + if ((m = mpls_shim_push(m, dstnew, NULL, NULL, NULL)) == 0) { + error = ENOBUFS; + goto done; + } + bosf = 0; + + break; + + case MPLS_OP_SWAP: /* Label Swap */ + default: + + if ((m = mpls_shim_swap(m, dstnew, NULL)) == 0) { + error = ENOBUFS; + goto done; + } + } + + ifp = rt->rt_ifp; + /* send to L2 : select outgoing i/f */ + switch (ifp->if_type) { + case IFT_ETHER: + case IFT_ATM: /* now only support scope 0 */ + case IFT_GIF: /* now only support scope 0 */ + error = (*ifp->if_output)(ifp, m, smplstosa(dstnew), rt); + goto done; + case IFT_LOOP: + break; + default: + /* not supported yet: discard */ +#ifdef MPLS_DEBUG + printf("mpls_lse: interface type not supported yet!\n"); +#endif /* MPLS_DEBUG */ + error = EHOSTUNREACH; + bad=1; + } + if (bad) break; + if (rt) { + RTFREE(rt); + rt = 0; + } + } /* The big inkloop for */ + + /* + * Discard broken packet + */ +if (bad) { +#ifdef MPLS_DEBUG + printf("MPLS_DEBUG: %s(%d) [packet discard!!].\n", __FILE__, __LINE__); +#endif /* MPLS_DEBUG */ + m_freem(m); +} + +done: + if (rt) + RTFREE(rt); + return(error); +} |