Hi, I want to commit this first bit of MPLS work this weekend or early next week. As usual, it was tested with Cisco implementation. Comments or objections anyone ? -- Mihai
? sys/netmpls ? usr.sbin/ldpd Index: distrib/sets/lists/base/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/base/mi,v retrieving revision 1.868 diff -u -p -r1.868 mi --- distrib/sets/lists/base/mi 14 Jun 2010 15:23:41 -0000 1.868 +++ distrib/sets/lists/base/mi 24 Jun 2010 06:43:11 -0000 @@ -793,6 +793,7 @@ ./usr/include/netisdn base-c-usr ./usr/include/netiso base-c-usr ./usr/include/netkey base-c-usr +./usr/include/netmpls base-c-usr ./usr/include/netnatm base-c-usr ./usr/include/netns base-obsolete obsolete ./usr/include/netsmb base-c-usr Index: distrib/sets/lists/comp/mi =================================================================== RCS file: /cvsroot/src/distrib/sets/lists/comp/mi,v retrieving revision 1.1466 diff -u -p -r1.1466 mi --- distrib/sets/lists/comp/mi 14 Jun 2010 14:50:47 -0000 1.1466 +++ distrib/sets/lists/comp/mi 24 Jun 2010 06:43:24 -0000 @@ -1454,6 +1454,7 @@ ./usr/include/net/if_ieee80211.h comp-obsolete obsolete ./usr/include/net/if_llc.h comp-c-include ./usr/include/net/if_media.h comp-c-include +./usr/include/net/if_mpls.h comp-c-include ./usr/include/net/if_pflog.h comp-c-include ./usr/include/net/if_ppp.h comp-c-include ./usr/include/net/if_pppoe.h comp-c-include @@ -1632,6 +1633,7 @@ ./usr/include/netiso/tp_user.h comp-c-include ./usr/include/netiso/tp_var.h comp-c-include ./usr/include/netiso/tuba_table.h comp-obsolete obsolete +./usr/include/netmpls/mpls.h comp-c-include ./usr/include/netkey/key.h comp-c-include ./usr/include/netkey/key_debug.h comp-c-include ./usr/include/netkey/key_var.h comp-c-include Index: sbin/route/keywords.c =================================================================== RCS file: /cvsroot/src/sbin/route/keywords.c,v retrieving revision 1.7 diff -u -p -r1.7 keywords.c --- sbin/route/keywords.c 12 May 2010 17:56:13 -0000 1.7 +++ sbin/route/keywords.c 24 Jun 2010 06:44:15 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: keywords.c,v 1.7 2010/05/12 17:56:13 christos Exp $ */ +/* $NetBSD$ */ /* WARNING! This file was generated by keywords.sh */ @@ -12,8 +12,6 @@ struct keytab keywords[] = { {"change", K_CHANGE}, {"cloned", K_CLONED}, {"cloning", K_CLONING}, - {"nocloned", K_NOCLONED}, - {"nocloning", K_NOCLONING}, {"delete", K_DELETE}, {"dst", K_DST}, {"expire", K_EXPIRE}, @@ -57,8 +55,12 @@ struct keytab keywords[] = { {"xns", K_XNS}, {"xresolve", K_XRESOLVE}, {"flushall", K_FLUSHALL}, + {"nocloned", K_NOCLONED}, + {"nocloning", K_NOCLONING}, {"noblackhole", K_NOBLACKHOLE}, {"noreject", K_NOREJECT}, + {"mpls", K_MPLS}, + {"tag", K_TAG}, {0, 0} }; Index: sbin/route/keywords.h =================================================================== RCS file: /cvsroot/src/sbin/route/keywords.h,v retrieving revision 1.10 diff -u -p -r1.10 keywords.h --- sbin/route/keywords.h 12 May 2010 17:56:13 -0000 1.10 +++ sbin/route/keywords.h 24 Jun 2010 06:44:15 -0000 @@ -1,4 +1,4 @@ -/* $NetBSD: keywords.h,v 1.10 2010/05/12 17:56:13 christos Exp $ */ +/* $NetBSD$ */ /* WARNING! This file was generated by keywords.sh */ @@ -61,3 +61,5 @@ extern struct keytab { #define K_NOCLONING 51 #define K_NOBLACKHOLE 52 #define K_NOREJECT 53 +#define K_MPLS 54 +#define K_TAG 55 Index: sbin/route/keywords.sh =================================================================== RCS file: /cvsroot/src/sbin/route/keywords.sh,v retrieving revision 1.8 diff -u -p -r1.8 keywords.sh --- sbin/route/keywords.sh 12 May 2010 19:26:33 -0000 1.8 +++ sbin/route/keywords.sh 24 Jun 2010 06:44:15 -0000 @@ -61,6 +61,8 @@ nocloned nocloning noblackhole noreject +mpls +tag _EOF_ Index: sbin/route/route.c =================================================================== RCS file: /cvsroot/src/sbin/route/route.c,v retrieving revision 1.120 diff -u -p -r1.120 route.c --- sbin/route/route.c 12 May 2010 17:56:13 -0000 1.120 +++ sbin/route/route.c 24 Jun 2010 06:44:15 -0000 @@ -57,6 +57,7 @@ __RCSID("$NetBSD: route.c,v 1.120 2010/0 #include <netinet/in.h> #include <netatalk/at.h> #include <netiso/iso.h> +#include <netmpls/mpls.h> #include <arpa/inet.h> #include <netdb.h> @@ -83,13 +84,14 @@ union sockunion { struct sockaddr_dl sdl; #ifndef SMALL struct sockaddr_iso siso; + struct sockaddr_mpls smpls; #endif /* SMALL */ }; typedef union sockunion *sup; struct sou { - union sockunion so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; + union sockunion so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp, so_mpls; }; static char *any_ntoa(const struct sockaddr *); @@ -121,7 +123,7 @@ static void sockaddr(const char *, struc int pid, rtm_addrs; int sock; int forcehost, forcenet, doflush, nflag, af, qflag, tflag, Sflag; -int iflag, verbose, aflen = sizeof(struct sockaddr_in); +int iflag, verbose, aflen = sizeof(struct sockaddr_in), rtag; int locking, lockrest, debugonly, shortoutput; struct rt_metrics rt_metrics; u_int32_t rtm_inits; @@ -575,6 +577,16 @@ routename(const struct sockaddr *sa, str ((const struct sockaddr_at *)sa)->sat_addr.s_net, ((const struct sockaddr_at *)sa)->sat_addr.s_node); break; + case AF_MPLS: + { + union mpls_shim ms; + + ms.s_addr =((const struct sockaddr_mpls*)sa)->smpls_addr.s_addr; + ms.s_addr = ntohl(ms.s_addr); + + snprintf(line, sizeof(line), "%u", ms.shim.label); + break; + } #endif /* SMALL */ default: @@ -819,6 +831,16 @@ newroute(int argc, char *const *argv) af = AF_ISO; aflen = sizeof(struct sockaddr_iso); break; + case K_MPLS: + af = AF_MPLS; + aflen = sizeof(struct sockaddr_mpls); + break; + case K_TAG: + if (!--argc) + usage(1+*argv); + aflen = sizeof(struct sockaddr_mpls); + (void)getaddr(RTA_TAG, *++argv, 0, soup); + break; #endif /* SMALL */ case K_IFACE: @@ -1140,6 +1162,10 @@ getaddr(int which, const char *s, struct su = &soup->so_ifa; su->sa.sa_family = af; break; + case RTA_TAG: + su = &soup->so_mpls; + afamily = AF_MPLS; + break; default: su = NULL; usage("Internal Error"); @@ -1245,6 +1271,16 @@ badataddr: su->sat.sat_addr.s_node = val; rtm_addrs |= RTA_NETMASK; return(forcehost || su->sat.sat_addr.s_node != 0); + case AF_MPLS: + if (atoi(s) < 0 || atoi(s) >> 20) /* ETOOMANYATOIS */ + errx(1, "bad tag: %s", s); + su->smpls.smpls_addr.s_addr = 0; + su->smpls.smpls_addr.shim.label = atoi(s); + su->smpls.smpls_addr.s_addr = + htonl(su->smpls.smpls_addr.s_addr); + + /* We don't have netmasks for tags */ + return 1; #endif case AF_LINK: @@ -1468,6 +1504,7 @@ rtmsg(int cmd, int flags, struct sou *so NEXTADDR(RTA_GENMASK, soup->so_genmask); NEXTADDR(RTA_IFP, soup->so_ifp); NEXTADDR(RTA_IFA, soup->so_ifa); + NEXTADDR(RTA_TAG, soup->so_mpls); rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; if (verbose && ! shortoutput) { if (rtm_addrs) @@ -1574,7 +1611,7 @@ const char routeflags[] = const char ifnetflags[] = "\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6NOTRAILERS\7RUNNING\010NOARP\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1\017LINK2\020MULTICAST"; const char addrnames[] = -"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; +"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD\011TAG"; #ifndef SMALL @@ -1739,7 +1776,7 @@ print_rtmsg(struct rt_msghdr *rtm, int m static int print_getmsg(struct rt_msghdr *rtm, int msglen, struct sou *soup) { - struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL; + struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL, *ifa = NULL, *mpls = NULL; struct sockaddr_dl *ifp = NULL; struct sockaddr *sa; char *cp; @@ -1785,6 +1822,9 @@ print_getmsg(struct rt_msghdr *rtm, int case RTA_IFA: ifa = sa; break; + case RTA_TAG: + mpls = sa; + break; } ADVANCE(cp, sa); } @@ -1812,6 +1852,17 @@ print_getmsg(struct rt_msghdr *rtm, int } else (void)printf(" gateway: %s\n", name); } + if (mpls) { + const char *name; + name = routename(mpls, NULL, RTF_HOST); + if(shortoutput) { + if (*name == '\0') + return 1; + printf("%s\n", name); + } else + printf(" Tag: %s\n", name); + } + if (ifa && ! shortoutput) (void)printf(" local addr: %s\n", routename(ifa, NULL, RTF_HOST)); @@ -1986,6 +2037,14 @@ sodump(sup su, const char *which) (void)printf("%s: iso %s; ", which, iso_ntoa(&su->siso.siso_addr)); break; + case AF_MPLS: + { + union mpls_shim ms; + ms.s_addr = ntohl(su->smpls.smpls_addr.s_addr); + printf("%s: mpls %u; ", + which, ms.shim.label); + } + break; #endif /* SMALL */ default: (void)printf("%s: (%d) %s; ", Index: sbin/route/show.c =================================================================== RCS file: /cvsroot/src/sbin/route/show.c,v retrieving revision 1.40 diff -u -p -r1.40 show.c --- sbin/route/show.c 26 Jan 2010 21:27:54 -0000 1.40 +++ sbin/route/show.c 24 Jun 2010 06:44:15 -0000 @@ -43,11 +43,13 @@ __RCSID("$NetBSD: show.c,v 1.40 2010/01/ #include <sys/socket.h> #include <sys/mbuf.h> +#include <arpa/inet.h> #include <net/if.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/route.h> #include <netinet/in.h> +#include <netmpls/mpls.h> #include <sys/sysctl.h> @@ -138,6 +140,10 @@ parse_show_opts(int argc, char * const * af = AF_ISO; afname = argv[argc - 1] + 1; break; + case K_MPLS: + af = AF_MPLS; + afname = argv[argc - 1] + 1; + break; #endif /* SMALL */ case K_LINK: if (nolink) @@ -319,6 +325,9 @@ pr_family(int af) case AF_ISO: afname = "ISO"; break; + case AF_MPLS: + afname = "MPLS"; + break; #endif /* SMALL */ case AF_APPLETALK: afname = "AppleTalk"; @@ -363,6 +372,18 @@ p_sockaddr(struct sockaddr *sa, struct s #endif /* INET6 */ #ifndef SMALL + case AF_MPLS: + { + struct sockaddr_mpls *smpls = (struct sockaddr_mpls *)sa; + union mpls_shim ms; + + ms.s_addr = ntohl(smpls->smpls_addr.s_addr); + + snprintf(workbuf, sizeof(workbuf), "%u", + ms.shim.label); + cp = workbuf; + } + break; case AF_APPLETALK: if (getnameinfo(sa, sa->sa_len, workbuf, sizeof(workbuf), NULL, 0, NI_NUMERICHOST) != 0) Index: sys/Makefile =================================================================== RCS file: /cvsroot/src/sys/Makefile,v retrieving revision 1.75 diff -u -p -r1.75 Makefile --- sys/Makefile 30 Dec 2008 22:18:11 -0000 1.75 +++ sys/Makefile 24 Jun 2010 06:44:18 -0000 @@ -2,7 +2,7 @@ SUBDIR= altq arch compat dev fs miscfs \ net net80211 netatalk netbt netipsec netinet netinet6 \ - netisdn netiso netkey netnatm netsmb \ + netisdn netiso netkey netmpls netnatm netsmb \ nfs opencrypto sys ufs uvm # interrupt implementation depends on the kernel within the port Index: sys/arch/amd64/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.281 diff -u -p -r1.281 GENERIC --- sys/arch/amd64/conf/GENERIC 2 Jun 2010 18:05:28 -0000 1.281 +++ sys/arch/amd64/conf/GENERIC 24 Jun 2010 06:44:19 -0000 @@ -1117,6 +1117,7 @@ pseudo-device tap # virtual Ethernet pseudo-device gre # generic L3 over IP tunnel pseudo-device gif # IPv[46] over IPv[46] tunnel (RFC1933) #pseudo-device faith # IPv[46] tcp relay translation i/f +#pseudo-device mpls # MultiProtocol Label Switching pseudo-device stf # 6to4 IPv6 over IPv4 encapsulation pseudo-device vlan # IEEE 802.1q encapsulation pseudo-device bridge # simple inter-network bridging Index: sys/arch/i386/conf/GENERIC =================================================================== RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v retrieving revision 1.984 diff -u -p -r1.984 GENERIC --- sys/arch/i386/conf/GENERIC 1 Jun 2010 02:40:13 -0000 1.984 +++ sys/arch/i386/conf/GENERIC 24 Jun 2010 06:44:22 -0000 @@ -1547,6 +1547,7 @@ pseudo-device tun # network tunneling pseudo-device gre # generic L3 over IP tunnel pseudo-device gif # IPv[46] over IPv[46] tunnel (RFC 1933) #pseudo-device faith # IPv[46] TCP relay translation i/f +#pseudo-device mpls # Multi Protocol Label Switching pseudo-device stf # 6to4 IPv6 over IPv4 encapsulation pseudo-device vlan # IEEE 802.1q encapsulation pseudo-device bridge # simple inter-network bridging Index: sys/conf/files =================================================================== RCS file: /cvsroot/src/sys/conf/files,v retrieving revision 1.989 diff -u -p -r1.989 files --- sys/conf/files 30 Apr 2010 20:47:17 -0000 1.989 +++ sys/conf/files 24 Jun 2010 06:44:26 -0000 @@ -1273,6 +1273,7 @@ defpseudo strip: ifnet defpseudo gre: ifnet defpseudo gif: ifnet defpseudo faith: ifnet +defpseudo mpls: ifnet defpseudo srt: ifnet defpseudo stf: ifnet defpseudodev tap: ifnet, ether, arp @@ -1611,6 +1612,9 @@ file net/if_hippisubr.c hippi needs-f file net/if_ieee1394subr.c ieee1394 file net/if_loop.c loop needs-flag file net/if_media.c +file net/if_mpls.c mpls needs-flag +file netmpls/mpls_proto.c mpls +file netmpls/mpls_ttl.c mpls file net/if_ppp.c ppp needs-flag file net/if_srt.c srt file net/if_stf.c stf & inet & inet6 needs-flag Index: sys/net/Makefile =================================================================== RCS file: /cvsroot/src/sys/net/Makefile,v retrieving revision 1.27 diff -u -p -r1.27 Makefile --- sys/net/Makefile 30 May 2009 09:04:35 -0000 1.27 +++ sys/net/Makefile 24 Jun 2010 06:44:30 -0000 @@ -4,7 +4,7 @@ INCSDIR= /usr/include/net INCS= bpf.h bpfdesc.h dlt.h ethertypes.h if.h if_arc.h if_arp.h \ if_atm.h if_bridgevar.h if_dl.h if_ether.h if_etherip.h if_fddi.h if_gif.h \ - if_gre.h if_hippi.h if_ieee1394.h if_llc.h if_media.h \ + if_gre.h if_hippi.h if_ieee1394.h if_llc.h if_media.h if_mpls.h \ if_pflog.h if_ppp.h if_pppoe.h if_sppp.h if_srt.h if_stf.h \ if_tap.h if_token.h if_tun.h if_types.h if_vlanvar.h net_stats.h \ netisr.h pfil.h pfkeyv2.h pfvar.h ppp-comp.h ppp_defs.h radix.h \ Index: sys/net/if_ethersubr.c =================================================================== RCS file: /cvsroot/src/sys/net/if_ethersubr.c,v retrieving revision 1.181 diff -u -p -r1.181 if_ethersubr.c --- sys/net/if_ethersubr.c 19 May 2010 20:43:51 -0000 1.181 +++ sys/net/if_ethersubr.c 24 Jun 2010 06:44:30 -0000 @@ -68,6 +68,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_ethersubr #include "opt_iso.h" #include "opt_ipx.h" #include "opt_mbuftrace.h" +#include "opt_mpls.h" #include "opt_gateway.h" #include "opt_pfil_hooks.h" #include "opt_pppoe.h" @@ -178,6 +179,11 @@ extern u_char at_org_code[3]; extern u_char aarp_org_code[3]; #endif /* NETATALK */ +#ifdef MPLS +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> +#endif + static struct timeval bigpktppslim_last; static int bigpktppslim = 2; /* XXX */ static int bigpktpps_count; @@ -447,6 +453,15 @@ ether_output(struct ifnet * const ifp0, senderr(EAFNOSUPPORT); } +#ifdef MPLS + if (rt0 != NULL && rt_gettag(rt0) != NULL) { + union mpls_shim msh; + msh.s_addr = MPLS_GETSADDR(rt0); + if (msh.shim.label != MPLS_LABEL_IMPLNULL) + etype = htons(ETHERTYPE_MPLS); + } +#endif + if (mcopy) (void)looutput(ifp, mcopy, dst, rt); @@ -508,7 +523,6 @@ ether_output(struct ifnet * const ifp0, if (ALTQ_IS_ENABLED(&ifp->if_snd)) altq_etherclassify(&ifp->if_snd, m, &pktattr); #endif - return ifq_enqueue(ifp, m ALTQ_COMMA ALTQ_DECL(&pktattr)); bad: @@ -640,7 +654,7 @@ ether_input(struct ifnet *ifp, struct mb /* * Determine if the packet is within its size limits. */ - if (m->m_pkthdr.len > + if (etype != ETHERTYPE_MPLS && m->m_pkthdr.len > ETHER_MAX_FRAME(ifp, etype, m->m_flags & M_HASFCS)) { if (ppsratecheck(&bigpktppslim_last, &bigpktpps_count, bigpktppslim)) { @@ -905,6 +919,12 @@ ether_input(struct ifnet *ifp, struct mb aarpinput(ifp, m); /* XXX */ return; #endif /* NETATALK */ +#ifdef MPLS + case ETHERTYPE_MPLS: + schednetisr(NETISR_MPLS); + inq = &mplsintrq; + break; +#endif default: m_freem(m); return; Index: sys/net/if_gre.c =================================================================== RCS file: /cvsroot/src/sys/net/if_gre.c,v retrieving revision 1.143 diff -u -p -r1.143 if_gre.c --- sys/net/if_gre.c 5 Apr 2010 07:22:23 -0000 1.143 +++ sys/net/if_gre.c 24 Jun 2010 06:44:30 -0000 @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1 #include "opt_atalk.h" #include "opt_gre.h" #include "opt_inet.h" +#include "opt_mpls.h" #include <sys/param.h> #include <sys/file.h> @@ -95,6 +96,11 @@ __KERNEL_RCSID(0, "$NetBSD: if_gre.c,v 1 #include <netinet6/in6_var.h> #endif +#ifdef MPLS +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> +#endif + #ifdef NETATALK #include <netatalk/at.h> #include <netatalk/at_var.h> @@ -899,6 +905,13 @@ gre_input(struct gre_softc *sc, struct m af = AF_INET6; break; #endif +#ifdef MPLS + case ETHERTYPE_MPLS: + ifq = &mplsintrq; + isr = NETISR_MPLS; + af = AF_MPLS; + break; +#endif default: /* others not yet supported */ GRE_DPRINTF(sc, "unhandled ethertype 0x%04x\n", ntohs(gh->ptype)); @@ -962,6 +975,14 @@ gre_output(struct ifnet *ifp, struct mbu * encapsulating protocol's ToS to suit. */ etype = htons(ETHERTYPE_IP); +#ifdef MPLS + if (rt != NULL && rt_gettag(rt) != NULL) { + union mpls_shim msh; + msh.s_addr = MPLS_GETSADDR(rt); + if (msh.shim.label != MPLS_LABEL_IMPLNULL) + etype = htons(ETHERTYPE_MPLS); + } +#endif break; #endif #ifdef NETATALK Index: sys/net/if_mpls.c =================================================================== RCS file: sys/net/if_mpls.c diff -N sys/net/if_mpls.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/net/if_mpls.c 24 Jun 2010 06:44:30 -0000 @@ -0,0 +1,599 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Mihai Chelaru <kefren%NetBSD.org@localhost> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD$"); + +#include "opt_inet.h" +#include "opt_mpls.h" + +#include <sys/param.h> + +#include <sys/errno.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/sysctl.h> + +#include <net/bpf.h> +#include <net/if.h> +#include <net/if_types.h> +#include <net/netisr.h> +#include <net/route.h> + +#ifdef INET +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> +#endif + +#ifdef INET6 +#include <netinet/ip6.h> +#include <netinet6/in6_var.h> +#include <netinet6/ip6_var.h> +#endif + +#include <netmpls/mpls.h> +#include <netmpls/mpls_var.h> + +#include "if_mpls.h" + +void mplsattach(int); + +static int mpls_clone_create(struct if_clone *, int); +static int mpls_clone_destroy(struct ifnet *); + +static struct if_clone mpls_if_cloner = + IF_CLONE_INITIALIZER("mpls", mpls_clone_create, mpls_clone_destroy); + + +static void mpls_input(struct ifnet *, struct mbuf *); +static int mpls_output(struct ifnet *, struct mbuf *, const struct sockaddr *, + struct rtentry *); +static int mpls_ioctl(struct ifnet *, u_long, void *); +static int mpls_send_frame(struct mbuf *, struct ifnet *, struct rtentry *); +static int mpls_lse(struct mbuf *); + +#ifdef INET +static int mpls_unlabel_inet(struct mbuf *); +static struct mbuf *mpls_label_inet(struct mbuf *, union mpls_shim *); +#endif + +#ifdef INET6 +static int mpls_unlabel_inet6(struct mbuf *); +static struct mbuf *mpls_label_inet6(struct mbuf *, union mpls_shim *); +#endif + +static struct mbuf *mpls_prepend_shim(struct mbuf *, union mpls_shim *); + +extern int mpls_defttl, mpls_mapttl_inet, mpls_mapttl_inet6, mpls_icmp_respond, + mpls_forwarding, mpls_accept, mpls_mapprec_inet, mpls_mapclass_inet6; + +/* ARGSUSED */ +void +mplsattach(int count) +{ + if_clone_attach(&mpls_if_cloner); +} + +static int +mpls_clone_create(struct if_clone *ifc, int unit) +{ + struct mpls_softc *sc; + + sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); + + if_initname(&sc->sc_if, ifc->ifc_name, unit); + sc->sc_if.if_softc = sc; + sc->sc_if.if_type = IFT_MPLS; + sc->sc_if.if_addrlen = 0; + sc->sc_if.if_hdrlen = sizeof(union mpls_shim); + sc->sc_if.if_dlt = DLT_NULL; + sc->sc_if.if_mtu = 1500; + sc->sc_if.if_flags = 0; + sc->sc_if.if_input = mpls_input; + sc->sc_if.if_output = mpls_output; + sc->sc_if.if_ioctl = mpls_ioctl; + + if_attach(&sc->sc_if); + if_alloc_sadl(&sc->sc_if); + bpf_attach(&sc->sc_if, DLT_NULL, sizeof(uint32_t)); + return 0; +} + +static int +mpls_clone_destroy(struct ifnet *ifp) +{ + int s; + + bpf_detach(ifp); + + s = splnet(); + if_detach(ifp); + splx(s); + + free(ifp->if_softc, M_DEVBUF); + return 0; +} + +static void +mpls_input(struct ifnet *ifp, struct mbuf *m) +{ +#if 0 + /* + * TODO - kefren + * I'd love to unshim the packet, guess family + * and pass it to bpf + */ + bpf_mtap_af(ifp, AF_MPLS, m); +#endif + + mpls_lse(m); +} + +void +mplsintr(void) +{ + struct mbuf *m; + int s; + + while (!IF_IS_EMPTY(&mplsintrq)) { + s = splnet(); + IF_DEQUEUE(&mplsintrq, m); + splx(s); + + if (!m) + return; + + if (((m->m_flags & M_PKTHDR) == 0) || + (m->m_pkthdr.rcvif == 0)) + panic("mplsintr(): no pkthdr or rcvif"); + +#ifdef MBUFTRACE + m_claimm(m, &mpls_owner); +#endif + mpls_input(m->m_pkthdr.rcvif, m); + } +} + +/* + * prepend shim and deliver + */ +static int +mpls_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, struct rtentry *rt) +{ + union mpls_shim mh; + struct rtentry *rt1; + int err; + + if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { + m_freem(m); + return ENETDOWN; + } + + if (rt_gettag(rt) == NULL) { + m_freem(m); + return EINVAL; + } + + bpf_mtap_af(ifp, dst->sa_family, m); + + mh.s_addr=MPLS_GETSADDR(rt); + mh.shim.bos=1; + mh.shim.exp=0; + mh.shim.ttl=mpls_defttl; + + switch(dst->sa_family) { +#ifdef INET + case AF_INET: + m = mpls_label_inet(m, &mh); + break; +#endif +#ifdef INET6 + case AF_INET6: + m = mpls_label_inet6(m, &mh); + break; +#endif + default: + m = mpls_prepend_shim(m, &mh); + break; + } + + if (m == NULL) { + IF_DROP(&ifp->if_snd); + ifp->if_oerrors++; + return ENOBUFS; + } + + ifp->if_opackets++; + ifp->if_obytes += m->m_pkthdr.len; + + if ((rt1=rtalloc1(rt->rt_gateway, 1)) == NULL) { + m_freem(m); + return EHOSTUNREACH; + } + + err = mpls_send_frame(m, rt1->rt_ifp, rt); + RTFREE(rt1); + return err; +} + +static int +mpls_ioctl(struct ifnet *ifp, u_long cmd, void *data) +{ + int error = 0, s = splnet(); + struct ifreq *ifr = data; + + switch(cmd) { + case SIOCINITIFADDR: + ifp->if_flags |= IFF_UP | IFF_RUNNING; + break; + case SIOCSIFMTU: + if (ifr != NULL && ifr->ifr_mtu < 576) { + error = EINVAL; + break; + } + /* FALLTHROUGH */ + case SIOCGIFMTU: + if ((error = ifioctl_common(ifp, cmd, data)) == ENETRESET) + error = 0; + break; + case SIOCSIFFLAGS: + if ((error = ifioctl_common(ifp, cmd, data)) != 0) + break; + if (ifp->if_flags & IFF_UP) + ifp->if_flags |= IFF_RUNNING; + break; + default: + error = ifioctl_common(ifp, cmd, data); + break; + } + splx(s); + return error; +} + +/* + * MPLS Label Switch Engine + */ +static int +mpls_lse(struct mbuf *m) +{ + struct sockaddr_mpls dst; + union mpls_shim tshim, *htag; + struct rtentry *rt = NULL; + int error = ENOBUFS; + + if (m->m_len < sizeof(union mpls_shim) && + (m = m_pullup(m, sizeof(union mpls_shim))) == NULL) + goto done; + + dst.smpls_len = sizeof(struct sockaddr_mpls); + dst.smpls_family = AF_MPLS; + dst.smpls_addr.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); + + /* Check if we're accepting MPLS Frames */ + error = EINVAL; + if (!mpls_accept) + goto done; + + /* TTL decrement */ + if ((m = mpls_ttl_dec(m)) == NULL) + goto done; + + if (dst.smpls_addr.shim.label <= MPLS_LABEL_RESMAX) { + /* Don't swap reserved labels */ + switch (dst.smpls_addr.shim.label) { +#ifdef INET + case MPLS_LABEL_IPV4NULL: + /* Pop shim and push mbuf to IP stack */ + if (dst.smpls_addr.shim.bos) + error = mpls_unlabel_inet(m); + break; +#endif +#ifdef INET6 + case MPLS_LABEL_IPV6NULL: + /* Pop shim and push mbuf to IPv6 stack */ + if (dst.smpls_addr.shim.bos) + error = mpls_unlabel_inet6(m); + break; +#endif + case MPLS_LABEL_RTALERT: /* Yeah, I'm all alerted */ + case MPLS_LABEL_IMPLNULL: /* This is logical only */ + default: /* Rest are not allowed */ + break; + } + goto done; + } + + /* Check if we should do MPLS forwarding */ + error = EHOSTUNREACH; + if (!mpls_forwarding) + goto done; + + /* Get a route to dst */ + dst.smpls_addr.shim.ttl = + dst.smpls_addr.shim.bos = + dst.smpls_addr.shim.exp = 0; + dst.smpls_addr.s_addr = htonl(dst.smpls_addr.s_addr); + if ((rt = rtalloc1((const struct sockaddr*)&dst, 1)) == NULL) + goto done; + + /* MPLS packet with no tagged route ? */ + if ((rt->rt_flags & RTF_GATEWAY) == 0 || + rt_gettag(rt) == NULL) + goto done; + + tshim.s_addr = MPLS_GETSADDR(rt); + + /* Swap labels */ + if ((m->m_len < sizeof(union mpls_shim)) && + (m = m_pullup(m, sizeof(union mpls_shim))) == 0) { + error = ENOBUFS; + goto done; + } + + /* Replace only the label */ + htag = mtod(m, union mpls_shim *); + htag->s_addr = ntohl(htag->s_addr); + htag->shim.label = tshim.shim.label; + htag->s_addr = htonl(htag->s_addr); + + error = mpls_send_frame(m, rt->rt_ifp, rt); + +done: + if (error != 0 && m != NULL) + m_freem(m); + if (rt != NULL) + RTFREE(rt); + + return error; +} + +static int +mpls_send_frame(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt) +{ + union mpls_shim msh; + + if ((rt->rt_flags & RTF_GATEWAY) == 0) + return EHOSTUNREACH; + + rt->rt_use++; + + msh.s_addr = MPLS_GETSADDR(rt); + if (msh.shim.label == MPLS_LABEL_IMPLNULL) { + m_adj(m, sizeof(union mpls_shim)); + m->m_pkthdr.csum_flags = 0; + } + + switch(ifp->if_type) { + /* only these two are supported for now */ + case IFT_ETHER: + case IFT_TUNNEL: + return (*ifp->if_output)(ifp, m, rt->rt_gateway, rt); + case IFT_LOOP: + break; + default: + return ENETUNREACH; + } + return 0; +} + + + +#ifdef INET +static int +mpls_unlabel_inet(struct mbuf *m) +{ + int s, iphlen; + struct ip *iph; + union mpls_shim *ms; + struct ifqueue *inq; + + if (mpls_mapttl_inet || mpls_mapprec_inet) { + + /* get shim info */ + ms = mtod(m, union mpls_shim *); + ms->s_addr = ntohl(ms->s_addr); + + /* and get rid of it */ + m_adj(m, sizeof(union mpls_shim)); + + /* get ip header */ + if (m->m_len < sizeof (struct ip) && + (m = m_pullup(m, sizeof(struct ip))) == NULL) + return ENOBUFS; + iph = mtod(m, struct ip *); + iphlen = iph->ip_hl << 2; + + /* get it all */ + if (m->m_len < iphlen) { + if ((m = m_pullup(m, iphlen)) == NULL) + return ENOBUFS; + iph = mtod(m, struct ip *); + } + + /* check ipsum */ + if (in_cksum(m, iphlen) != 0) { + m_freem(m); + return EINVAL; + } + + /* set IP ttl from MPLS ttl */ + if (mpls_mapttl_inet) + iph->ip_ttl = ms->shim.ttl; + + /* set IP Precedence from MPLS Exp */ + if (mpls_mapprec_inet) { + iph->ip_tos = (iph->ip_tos << 3) >> 3; + iph->ip_tos |= ms->shim.exp << 5; + } + + /* reset ipsum because we modified TTL and TOS */ + iph->ip_sum = 0; + iph->ip_sum = in_cksum(m, iphlen); + } else + m_adj(m, sizeof(union mpls_shim)); + + /* Put it on IP queue */ + inq = &ipintrq; + s = splnet(); + if (IF_QFULL(inq)) { + IF_DROP(inq); + splx(s); + m_freem(m); + return ENOBUFS; + } + IF_ENQUEUE(inq, m); + splx(s); + schednetisr(NETISR_IP); + + return 0; +} + +/* + * Prepend MPLS label + */ +static struct mbuf * +mpls_label_inet(struct mbuf *m, union mpls_shim *ms) +{ + struct ip *iphdr; + + if (mpls_mapttl_inet || mpls_mapprec_inet) { + if ((m->m_len < sizeof(struct ip)) && + (m = m_pullup(m, sizeof(struct ip))) == 0) + return NULL; + iphdr = mtod(m, struct ip *); + + /* Map TTL */ + if (mpls_mapttl_inet) + ms->shim.ttl = iphdr->ip_ttl; + + /* Copy IP precedence to EXP */ + if (mpls_mapprec_inet) + ms->shim.exp = ((u_int8_t)iphdr->ip_tos) >> 5; + } + + if ((m = mpls_prepend_shim(m, ms)) == NULL) + return NULL; + + return m; +} + +#endif /* INET */ + +#ifdef INET6 + +static int +mpls_unlabel_inet6(struct mbuf *m) +{ + struct ip6_hdr *ip6hdr; + union mpls_shim ms; + struct ifqueue *inq; + int s; + + /* TODO: mapclass */ + if (mpls_mapttl_inet6) { + ms.s_addr = ntohl(mtod(m, union mpls_shim *)->s_addr); + m_adj(m, sizeof(union mpls_shim)); + + if (m->m_len < sizeof (struct ip6_hdr) && + (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) + return ENOBUFS; + ip6hdr = mtod(m, struct ip6_hdr *); + + /* Because we just decremented this in mpls_lse */ + ip6hdr->ip6_hlim = ms.shim.ttl + 1; + } else + m_adj(m, sizeof(union mpls_shim)); + + /* Put it back on IPv6 stack */ + schednetisr(NETISR_IPV6); + inq = &ip6intrq; + s = splnet(); + if (IF_QFULL(inq)) { + IF_DROP(inq); + splx(s); + m_freem(m); + return ENOBUFS; + } + + IF_ENQUEUE(inq, m); + splx(s); + + return 0; +} + +static struct mbuf * +mpls_label_inet6(struct mbuf *m, union mpls_shim *ms) +{ + struct ip6_hdr *ip6h; + + if (mpls_mapttl_inet6 || mpls_mapclass_inet6) { + if (m->m_len < sizeof(struct ip6_hdr) && + (m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) + return NULL; + ip6h = mtod(m, struct ip6_hdr *); + + if (mpls_mapttl_inet6) + ms->shim.ttl = ip6h->ip6_hlim; + + if (mpls_mapclass_inet6) + ms->shim.exp = ip6h->ip6_vfc << 1 >> 5; + } + + if ((m = mpls_prepend_shim(m, ms)) == NULL) + return NULL; + + return m; +} + +#endif /* INET6 */ + +static struct mbuf * +mpls_prepend_shim(struct mbuf *m, union mpls_shim *ms) +{ + union mpls_shim *shim; + + M_PREPEND(m, sizeof(*ms), M_DONTWAIT); + if (m == NULL) + return NULL; + + if (m->m_len < sizeof(union mpls_shim) && + (m = m_pullup(m, sizeof(union mpls_shim))) == 0) + return NULL; + + shim = mtod(m, union mpls_shim *); + + memcpy(shim, ms, sizeof(*shim)); + shim->s_addr = htonl(shim->s_addr); + + return m; +} Index: sys/net/if_mpls.h =================================================================== RCS file: sys/net/if_mpls.h diff -N sys/net/if_mpls.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/net/if_mpls.h 24 Jun 2010 06:44:30 -0000 @@ -0,0 +1,41 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2010 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Mihai Chelaru <kefren%NetBSD.org@localhost> + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef _NET_IF_MPLS_H_ +#define _NET_IF_MPLS_H_ + + +struct mpls_softc { + struct ifnet sc_if; +}; + + +#endif /* _NET_IF_MPLS_H_ */ Index: sys/net/netisr.h =================================================================== RCS file: /cvsroot/src/sys/net/netisr.h,v retrieving revision 1.39 diff -u -p -r1.39 netisr.h --- sys/net/netisr.h 12 Nov 2008 12:36:28 -0000 1.39 +++ sys/net/netisr.h 24 Jun 2010 06:44:31 -0000 @@ -52,6 +52,7 @@ #include "opt_inet.h" #include "opt_atalk.h" #include "opt_iso.h" +#include "opt_mpls.h" #include "opt_natm.h" #include "arp.h" #endif /* defined(_KERNEL_OPT) */ @@ -85,6 +86,9 @@ #include <netiso/iso.h> #include <netiso/clnp.h> #endif +#ifdef MPLS +#include <netmpls/mpls_var.h> +#endif #ifdef NATM #include <netnatm/natm.h> #endif @@ -112,6 +116,7 @@ #define NETISR_ISDN 26 /* same as AF_E164 */ #define NETISR_NATM 27 /* same as AF_NATM */ #define NETISR_ARP 28 /* same as AF_ARP */ +#define NETISR_MPLS 33 /* same as AF_MPLS */ #define NETISR_MAX AF_MAX #if !defined(_LOCORE) && defined(_KERNEL) Index: sys/net/netisr_dispatch.h =================================================================== RCS file: /cvsroot/src/sys/net/netisr_dispatch.h,v retrieving revision 1.14 diff -u -p -r1.14 netisr_dispatch.h --- sys/net/netisr_dispatch.h 14 Jul 2007 21:02:42 -0000 1.14 +++ sys/net/netisr_dispatch.h 24 Jun 2010 06:44:31 -0000 @@ -42,6 +42,9 @@ #ifdef ISO DONETISR(NETISR_ISO,clnlintr); #endif +#ifdef MPLS + DONETISR(NETISR_MPLS,mplsintr); +#endif #ifdef NATM DONETISR(NETISR_NATM,natmintr); #endif Index: sys/net/route.c =================================================================== RCS file: /cvsroot/src/sys/net/route.c,v retrieving revision 1.122 diff -u -p -r1.122 route.c --- sys/net/route.c 2 May 2010 19:17:56 -0000 1.122 +++ sys/net/route.c 24 Jun 2010 06:44:31 -0000 @@ -804,6 +804,8 @@ rtrequest1(int req, struct rt_addrinfo * RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); } rt_set_ifa(rt, ifa); + if (info->rti_info[RTAX_TAG] != NULL) + rt_settag(rt, info->rti_info[RTAX_TAG]); RT_DPRINTF("rt->_rt_key = %p\n", (void *)rt->_rt_key); if (info->rti_info[RTAX_IFP] != NULL && (ifa2 = ifa_ifwithnet(info->rti_info[RTAX_IFP])) != NULL && @@ -1413,3 +1415,20 @@ rt_walktree(sa_family_t family, int (*f) return rn_walktree(rnh, rt_walktree_visitor, &rw); } + +const struct sockaddr * +rt_settag(struct rtentry *rt, const struct sockaddr *tag) +{ + if (rt->rt_tag != tag) { + if (rt->rt_tag != NULL) + sockaddr_free(rt->rt_tag); + rt->rt_tag = sockaddr_dup(tag, M_NOWAIT); + } + return rt->rt_tag; +} + +struct sockaddr * +rt_gettag(struct rtentry *rt) +{ + return rt->rt_tag; +} Index: sys/net/route.h =================================================================== RCS file: /cvsroot/src/sys/net/route.h,v retrieving revision 1.74 diff -u -p -r1.74 route.h --- sys/net/route.h 3 Nov 2009 00:30:31 -0000 1.74 +++ sys/net/route.h 24 Jun 2010 06:44:31 -0000 @@ -126,7 +126,8 @@ struct rtentry { struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */ LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */ struct rtentry *rt_parent; /* parent of cloned route */ - struct sockaddr *_rt_key; + struct sockaddr *_rt_key; + struct sockaddr *rt_tag; /* route tagging info */ }; static inline const struct sockaddr * @@ -243,6 +244,7 @@ struct rt_msghdr { #define RTA_IFA 0x20 /* interface addr sockaddr present */ #define RTA_AUTHOR 0x40 /* sockaddr for author of redirect */ #define RTA_BRD 0x80 /* for NEWADDR, broadcast or p-p dest addr */ +#define RTA_TAG 0x100 /* route tag */ /* * Index offsets for sockaddr array for alternate internal encoding. @@ -255,7 +257,8 @@ struct rt_msghdr { #define RTAX_IFA 5 /* interface addr sockaddr present */ #define RTAX_AUTHOR 6 /* sockaddr for author of redirect */ #define RTAX_BRD 7 /* for NEWADDR, broadcast or p-p dest addr */ -#define RTAX_MAX 8 /* size of array to allocate */ +#define RTAX_TAG 8 /* route tag */ +#define RTAX_MAX 9 /* size of array to allocate */ #define RT_ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -276,6 +279,7 @@ struct route_cb { int ipx_count; int ns_count; int iso_count; + int mpls_count; int any_count; }; @@ -383,6 +387,9 @@ int rtrequest1(int, struct rt_addrinfo struct ifaddr *rt_get_ifa(struct rtentry *); void rt_replace_ifa(struct rtentry *, struct ifaddr *); +const struct sockaddr *rt_settag(struct rtentry *, const struct sockaddr *); +struct sockaddr *rt_gettag(struct rtentry *); + static inline void rt_destroy(struct rtentry *rt) { @@ -390,7 +397,9 @@ rt_destroy(struct rtentry *rt) sockaddr_free(rt->_rt_key); if (rt->rt_gateway != NULL) sockaddr_free(rt->rt_gateway); - rt->_rt_key = rt->rt_gateway = NULL; + if (rt_gettag(rt) != NULL) + sockaddr_free(rt_gettag(rt)); + rt->_rt_key = rt->rt_gateway = rt->rt_tag = NULL; } static inline const struct sockaddr * Index: sys/net/rtsock.c =================================================================== RCS file: /cvsroot/src/sys/net/rtsock.c,v retrieving revision 1.128 diff -u -p -r1.128 rtsock.c --- sys/net/rtsock.c 2 May 2010 19:17:56 -0000 1.128 +++ sys/net/rtsock.c 24 Jun 2010 06:44:32 -0000 @@ -64,6 +64,7 @@ __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.128 2010/05/02 19:17:56 kefren Exp $"); #include "opt_inet.h" +#include "opt_mpls.h" #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" #endif @@ -87,6 +88,8 @@ __KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1 #include <net/route.h> #include <net/raw_cb.h> +#include <netmpls/mpls.h> + #if defined(COMPAT_14) || defined(COMPAT_50) #include <compat/net/if.h> #endif @@ -128,12 +131,15 @@ rt_adjustcount(int af, int cnt) case AF_IPX: route_cb.ipx_count += cnt; return; - case AF_NS: - route_cb.ns_count += cnt; - return; case AF_ISO: route_cb.iso_count += cnt; return; + case AF_MPLS: + route_cb.mpls_count += cnt; + return; + case AF_NS: + route_cb.ns_count += cnt; + return; } } @@ -339,6 +345,7 @@ route_output(struct mbuf *m, ...) info.rti_info[RTAX_DST] = rt_getkey(rt); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_NETMASK] = rt_mask(rt); + info.rti_info[RTAX_TAG] = (struct sockaddr*)rt_gettag(rt); if ((rtm->rtm_addrs & (RTA_IFP | RTA_IFA)) == 0) ; else if ((ifp = rt->rt_ifp) != NULL) { @@ -403,6 +410,8 @@ route_output(struct mbuf *m, ...) if (info.rti_info[RTAX_GATEWAY] && rt_setgate(rt, info.rti_info[RTAX_GATEWAY])) senderr(EDQUOT); + if (info.rti_info[RTAX_TAG]) + rt_settag(rt, info.rti_info[RTAX_TAG]); /* new gateway could require new ifaddr, ifp; flags may also be different; ifp may be specified by ll sockaddr when protocol address is ambiguous */ Index: sys/netinet/ip_icmp.c =================================================================== RCS file: /cvsroot/src/sys/netinet/ip_icmp.c,v retrieving revision 1.122 diff -u -p -r1.122 ip_icmp.c --- sys/netinet/ip_icmp.c 7 Dec 2009 18:47:24 -0000 1.122 +++ sys/netinet/ip_icmp.c 24 Jun 2010 06:44:32 -0000 @@ -177,8 +177,6 @@ static struct rttimer_queue *icmp_redire static void icmp_mtudisc_timeout(struct rtentry *, struct rttimer *); static void icmp_redirect_timeout(struct rtentry *, struct rttimer *); -static int icmp_ratelimit(const struct in_addr *, const int, const int); - static void sysctl_netinet_icmp_setup(struct sysctllog **); void @@ -1251,7 +1249,7 @@ icmp_redirect_timeout(struct rtentry *rt * * XXX per-destination/type check necessary? */ -static int +int icmp_ratelimit(const struct in_addr *dst, const int type, const int code) { Index: sys/netinet/ip_icmp.h =================================================================== RCS file: /cvsroot/src/sys/netinet/ip_icmp.h,v retrieving revision 1.25 diff -u -p -r1.25 ip_icmp.h --- sys/netinet/ip_icmp.h 8 Sep 2008 23:36:55 -0000 1.25 +++ sys/netinet/ip_icmp.h 24 Jun 2010 06:44:32 -0000 @@ -184,6 +184,7 @@ void icmp_send(struct mbuf *, struct mbu int icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t); void icmp_mtudisc_callback_register(void (*)(struct in_addr)); +int icmp_ratelimit(const struct in_addr *, const int, const int); #endif Index: sys/rump/net/lib/libnet/opt/opt_mpls.h =================================================================== RCS file: sys/rump/net/lib/libnet/opt/opt_mpls.h diff -N sys/rump/net/lib/libnet/opt/opt_mpls.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/rump/net/lib/libnet/opt/opt_mpls.h 24 Jun 2010 06:44:33 -0000 @@ -0,0 +1,3 @@ +/* $NetBSD:$ */ + +/* XXX: dummy */ Index: sys/sys/socket.h =================================================================== RCS file: /cvsroot/src/sys/sys/socket.h,v retrieving revision 1.97 diff -u -p -r1.97 socket.h --- sys/sys/socket.h 5 Dec 2009 20:11:18 -0000 1.97 +++ sys/sys/socket.h 24 Jun 2010 06:44:33 -0000 @@ -210,8 +210,8 @@ struct accept_filter_arg { #endif #define AF_BLUETOOTH 31 /* Bluetooth: HCI, SCO, L2CAP, RFCOMM */ #define AF_IEEE80211 32 /* IEEE80211 */ - -#define AF_MAX 33 +#define AF_MPLS 33 /* MultiProtocol Label Switching */ +#define AF_MAX 34 /* * Structure used by kernel to store most @@ -300,6 +300,7 @@ struct sockaddr_storage { #define PF_KEY pseudo_AF_KEY /* like PF_ROUTE, only for key mgmt */ #endif #define PF_BLUETOOTH AF_BLUETOOTH +#define PF_MPLS AF_MPLS #define PF_MAX AF_MAX Index: usr.bin/netstat/show.c =================================================================== RCS file: /cvsroot/src/usr.bin/netstat/show.c,v retrieving revision 1.8 diff -u -p -r1.8 show.c --- usr.bin/netstat/show.c 13 Sep 2009 02:53:17 -0000 1.8 +++ usr.bin/netstat/show.c 24 Jun 2010 06:44:37 -0000 @@ -44,6 +44,7 @@ #include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> +#include <netmpls/mpls.h> #include <arpa/inet.h> #include <err.h> @@ -59,6 +60,7 @@ char *any_ntoa(const struct sockaddr *); char *link_print(struct sockaddr *); +char *mpls_ntoa(const struct sockaddr *); #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -288,6 +290,9 @@ pr_family(int paf) case AF_APPLETALK: afname = "AppleTalk"; break; + case AF_MPLS: + afname = "MPLS"; + break; default: afname = NULL; break; @@ -420,6 +425,9 @@ routename(struct sockaddr *sa) case AF_LINK: return (link_print(sa)); + case AF_MPLS: + return mpls_ntoa(sa); + #if 0 /* XXX-elad */ case AF_UNSPEC: if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) { @@ -684,3 +692,19 @@ link_print(struct sockaddr *sa) return (link_ntoa(sdl)); } } + +char * +mpls_ntoa(const struct sockaddr *sa) +{ + static char obuf[100]; + const struct sockaddr_mpls *sm; + union mpls_shim ms; + + sm = (const struct sockaddr_mpls*)sa; + ms.s_addr = ntohl(sm->smpls_addr.s_addr); + + snprintf(obuf, sizeof(obuf), "%u", + ms.shim.label); + + return obuf; +}
Attachment:
f1-sysnetmpls.tar
Description: Binary data