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