tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

MPLS patches (again)



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



Home | Main Index | Thread Index | Old Index