iproute2: MPLS support
Subsystems (4)
PATCH 1/1 iproute2: MPLS support
This set of changes adds support for nexthops in different address families, with the new netlink RTA_VIA option.
Support is added for routes that change the destination address (as MPLS does) with the RTA_NEWDST attribute.
Support for MPLS addresses is added (for multiple labels I had to make up the syntax I used label/label/label as it fits in well with addresses that don't have a space in them).
Support for these options is merged into David's net-next kernel tree, and the meaning of the options is unlikely to change in any significant way before this code merges upstream.
The documentation has been updated to report that the new options are present and to report roughly what they do. This includes ip --help and the man pages.
Eric W. Biederman (8):
iproute2: Add a source addres length parameter to rt_addr_n2a
iproute2: Make the addr argument of ll_addr_n2a const
iproute2: Add support for printing AF_PACKET addresses
iproute2: Add address family to/from string helper functions.
iproute2: misc whitespace cleanup
iproute2: Add support for RTA_VIA attributes
iproute2: Add support for the RTA_NEWDST attribute.
iproute2: Add basic mpls support to iproute
Makefile | 3 ++ include/linux/mpls.h | 34 +++++++++++++++ include/linux/rtnetlink.h | 10 +++++ include/rt_names.h | 2 +- include/utils.h | 22 ++++++++-- ip/ip.c | 20 +++------ ip/iplink_bond.c | 1 + ip/ipmonitor.c | 3 ++ ip/ipmroute.c | 2 + ip/ipprefix.c | 4 +- ip/iproute.c | 108 ++++++++++++++++++++++++++++++++++++++++------ ip/iprule.c | 10 +++-- ip/iptunnel.c | 4 +- ip/ipxfrm.c | 17 +++++--- ip/link_ip6tnl.c | 2 + ip/xfrm_monitor.c | 8 ++-- lib/ll_addr.c | 2 +- lib/mpls_ntop.c | 48 +++++++++++++++++++++ lib/mpls_pton.c | 58 +++++++++++++++++++++++++ lib/utils.c | 91 ++++++++++++++++++++++++++++++++++---- man/man8/ip-route.8.in | 23 +++++++--- man/man8/ip.8 | 7 ++- 22 files changed, 413 insertions(+), 66 deletions(-)
PATCH 1/8 iproute2: Add a source addres length parameter to rt_addr_n2a
For some address families (like AF_PACKET) it is helpful to have the length when printing the address.
--- include/utils.h | 2 +- ip/iplink_bond.c | 1 + ip/ipmroute.c | 2 ++ ip/ipprefix.c | 4 +++- ip/iproute.c | 11 +++++++---- ip/iprule.c | 10 ++++++---- ip/iptunnel.c | 2 +- ip/ipxfrm.c | 17 +++++++++++------ ip/link_ip6tnl.c | 2 ++ ip/xfrm_monitor.c | 8 +++++--- lib/utils.c | 4 ++-- 11 files changed, 41 insertions(+), 22 deletions(-)
include/utils.h +1 -1
@@ -103,7 +103,7 @@ extern __u8* hexstring_a2n(const char *str, __u8 *buf, int blen);extern const char *format_host (int af,int len,const void *addr,char *buf,int buflen); -extern const char *rt_addr_n2a (int af,const void *addr, +extern const char *rt_addr_n2a (int af,int len,const void *addr,char *buf,int buflen);void missarg (const char *) __attribute__((noreturn));
ip/iplink_bond.c +1 -0
@@ -415,6 +415,7 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])if (iptb[i])fprintf (f,"%s" ,rt_addr_n2a (AF_INET , +RTA_PAYLOAD (iptb[i]),RTA_DATA (iptb[i]), buf,INET_ADDRSTRLEN ));
ip/ipmroute.c +2 -0
@@ -116,6 +116,7 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_SRC ]) len =snprintf (obuf,sizeof (obuf),"(%s, " ,rt_addr_n2a (family, +RTA_PAYLOAD (tb[RTA_SRC ]),RTA_DATA (tb[RTA_SRC ]), abuf,sizeof (abuf)));else
@@ -123,6 +124,7 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_DST ])snprintf (obuf + len,sizeof (obuf) - len,"%s)" ,rt_addr_n2a (family, +RTA_PAYLOAD (tb[RTA_DST ]),RTA_DATA (tb[RTA_DST ]), abuf,sizeof (abuf)));else
ip/ipprefix.c +3 -1
@@ -80,7 +80,9 @@ int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) pfx = (struct in6_addr *)RTA_DATA (tb[PREFIX_ADDRESS ]);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"%s" ,rt_addr_n2a (family, pfx, +fprintf (fp,"%s" ,rt_addr_n2a (family, +RTA_PAYLOAD (tb[PREFIX_ADDRESS ]), + pfx, abuf,sizeof (abuf))); }fprintf (fp,"/%u " , prefix->prefix_len);
ip/iproute.c +7 -4
@@ -353,8 +353,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_DST ]) {if (r->rtm_dst_len != host_len) {fprintf (fp,"%s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[RTA_DST ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[RTA_DST ]), +RTA_DATA (tb[RTA_DST ]), + abuf,sizeof (abuf)), r->rtm_dst_len ); }else {
@@ -372,8 +373,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_SRC ]) {if (r->rtm_src_len != host_len) {fprintf (fp,"from %s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[RTA_SRC ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[RTA_SRC ]), +RTA_DATA (tb[RTA_SRC ]), + abuf,sizeof (abuf)), r->rtm_src_len ); }else {
@@ -415,6 +417,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)*/ fprintf (fp," src %s " ,rt_addr_n2a (r->rtm_family, +RTA_PAYLOAD (tb[RTA_PREFSRC ]),RTA_DATA (tb[RTA_PREFSRC ]), abuf,sizeof (abuf))); }
ip/iprule.c +6 -4
@@ -89,8 +89,9 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[FRA_SRC ]) {if (r->rtm_src_len != host_len) {fprintf (fp,"from %s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[FRA_SRC ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[FRA_SRC ]), +RTA_DATA (tb[FRA_SRC ]), + abuf,sizeof (abuf)), r->rtm_src_len ); }else {
@@ -109,8 +110,9 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[FRA_DST ]) {if (r->rtm_dst_len != host_len) {fprintf (fp,"to %s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[FRA_DST ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[FRA_DST ]), +RTA_DATA (tb[FRA_DST ]), + abuf,sizeof (abuf)), r->rtm_dst_len ); }else {
ip/iptunnel.c +1 -1
@@ -343,7 +343,7 @@ static void print_tunnel(struct ip_tunnel_parm *p) p->name,tnl_strproto (p->iph.protocol), p->iph.daddr ?format_host (AF_INET ,4 , &p->iph.daddr, s1,sizeof (s1)) :"any" , - p->iph.saddr ? rt_addr_n2a(AF_INET, &p->iph.saddr, s2, sizeof(s2)) : "any"); + p->iph.saddr ? rt_addr_n2a(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2)) : "any");if (p->iph.protocol ==IPPROTO_IPV6 && (p->i_flags &SIT_ISATAP )) {struct ip_tunnel_prl prl[16 ];
ip/ipxfrm.c +11 -6
@@ -288,10 +288,10 @@ void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id,fputs (title, fp);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"src %s " ,rt_addr_n2a (family, +fprintf (fp,"src %s " ,rt_addr_n2a (family,sizeof (*saddr), saddr, abuf,sizeof (abuf)));memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"dst %s" ,rt_addr_n2a (family, +fprintf (fp,"dst %s" ,rt_addr_n2a (family,sizeof (id->daddr), &id->daddr, abuf,sizeof (abuf)));fprintf (fp,"%s" , _SL_);
@@ -455,11 +455,15 @@ void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,fputs (prefix, fp);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"src %s/%u " ,rt_addr_n2a (f, &sel->saddr, abuf,sizeof (abuf)), +fprintf (fp,"src %s/%u " , +rt_addr_n2a (f,sizeof (sel->saddr), &sel->saddr, + abuf,sizeof (abuf)), sel->prefixlen_s);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"dst %s/%u " ,rt_addr_n2a (f, &sel->daddr, abuf,sizeof (abuf)), +fprintf (fp,"dst %s/%u " , +rt_addr_n2a (f,sizeof (sel->daddr), &sel->daddr, + abuf,sizeof (abuf)), sel->prefixlen_d);if (sel->proto)
@@ -754,7 +758,8 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,memset (abuf,'\0' ,sizeof (abuf));fprintf (fp,"addr %s" , -rt_addr_n2a (family, &e->encap_oa, abuf,sizeof (abuf))); +rt_addr_n2a (family,sizeof (e->encap_oa), &e->encap_oa, + abuf,sizeof (abuf)));fprintf (fp,"%s" , _SL_); }
@@ -782,7 +787,7 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,memset (abuf,'\0' ,sizeof (abuf));fprintf (fp,"%s" , -rt_addr_n2a (family, coa, +rt_addr_n2a (family,sizeof (*coa), coa, abuf,sizeof (abuf)));fprintf (fp,"%s" , _SL_); }
ip/link_ip6tnl.c +2 -0
@@ -285,6 +285,7 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tbif (tb[IFLA_IPTUN_REMOTE ]) {fprintf (f,"remote %s " ,rt_addr_n2a (AF_INET6 , +RTA_PAYLOAD (tb[IFLA_IPTUN_REMOTE ]),RTA_DATA (tb[IFLA_IPTUN_REMOTE ]), s1,sizeof (s1))); }
@@ -292,6 +293,7 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tbif (tb[IFLA_IPTUN_LOCAL ]) {fprintf (f,"local %s " ,rt_addr_n2a (AF_INET6 , +RTA_PAYLOAD (tb[IFLA_IPTUN_LOCAL ]),RTA_DATA (tb[IFLA_IPTUN_LOCAL ]), s1,sizeof (s1))); }
ip/xfrm_monitor.c +5 -3
@@ -227,7 +227,8 @@ static void xfrm_usersa_print(const struct xfrm_usersa_id *sa_id, __u32 reqid, F buf[0 ] =0 ;fprintf (fp,"dst %s " , -rt_addr_n2a (sa_id->family, &sa_id->daddr, buf,sizeof (buf))); +rt_addr_n2a (sa_id->family,sizeof (sa_id->daddr), &sa_id->daddr, + buf,sizeof (buf)));fprintf (fp," reqid 0x%x" , reqid);
@@ -246,7 +247,8 @@ static int xfrm_ae_print(const struct sockaddr_nl *who,xfrm_ae_flags_print (id->flags, arg);fprintf (fp,"\n\t" );memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"src %s " ,rt_addr_n2a (id->sa_id.family, &id->saddr, +fprintf (fp,"src %s " ,rt_addr_n2a (id->sa_id.family, +sizeof (id->saddr), &id->saddr, abuf,sizeof (abuf)));xfrm_usersa_print (&id->sa_id, id->reqid, fp);
@@ -262,7 +264,7 @@ static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a)char buf[256 ]; buf[0 ] =0 ; -fprintf (fp,"%s" ,rt_addr_n2a (family, a, buf,sizeof (buf))); +fprintf (fp,"%s" ,rt_addr_n2a (family,sizeof (*a), a, buf,sizeof (buf))); } static int xfrm_mapping_print(const struct sockaddr_nl *who,
lib/utils.c +2 -2
@@ -624,7 +624,7 @@ int __get_user_hz(void)return sysconf (_SC_CLK_TCK); } -const char *rt_addr_n2a (int af,const void *addr,char *buf,int buflen) +const char *rt_addr_n2a (int af,int len,const void *addr,char *buf,int buflen) {switch (af) {case AF_INET :
@@ -731,7 +731,7 @@ const char *format_host(int af, int len, const void *addr, return n; }#endif -return rt_addr_n2a (af, addr, buf, buflen); +return rt_addr_n2a (af, len, addr, buf, buflen); }
Signature · 1 line
2.2.1
PATCH 2/8 iproute2: Make the addr argument of ll_addr_n2a const
In reply to Eric W. BiedermanThis avoids build warnings when AF_PACKET support is added to rt_addr_n2a.
--- include/rt_names.h | 2 +- lib/ll_addr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/rt_names.h +1 -1
@@ -22,7 +22,7 @@ int inet_proto_a2n(const char *buf);const char *ll_type_n2a (int type,char *buf,int len); -const char *ll_addr_n2a (unsigned char *addr,int alen, +const char *ll_addr_n2a (const unsigned char *addr,int alen,int type,char *buf,int blen);int ll_addr_a2n (char *lladdr,int len,const char *arg);
lib/ll_addr.c +1 -1
@@ -29,7 +29,7 @@#include "utils.h" -const char *ll_addr_n2a (unsigned char *addr,int alen,int type,char *buf,int blen) +const char *ll_addr_n2a (const unsigned char *addr,int alen,int type,char *buf,int blen) {int i;int l;
Signature · 1 line
2.2.1
PATCH 3/8 iproute2: Add support for printing AF_PACKET addresses
In reply to Eric W. Biederman--- lib/utils.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
lib/utils.c +16 -5
@@ -25,11 +25,12 @@#include <asm/types.h> #include <linux/pkt_sched.h> #include <linux/param.h> +#include <linux/if_arp.h> #include <time.h> #include <sys/time.h> #include <errno.h> - +#include "rt_names.h" #include "utils.h" #include "namespace.h"
@@ -397,6 +398,18 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)return 0 ; } +if (family ==AF_PACKET ) { +int len; + len =ll_addr_a2n ((char *)&addr->data,sizeof (addr->data), name); +if (len <0 ) +return -1 ; + + addr->family =AF_PACKET ; + addr->bytelen = len; + addr->bitlen = len *8 ; +return 0 ; + } +if (strchr (name,':' )) { addr->family =AF_INET6 ;if (family !=AF_UNSPEC && family !=AF_INET6 )
@@ -485,10 +498,6 @@ done:int get_addr (inet_prefix *dst,const char *arg,int family) { -if (family ==AF_PACKET ) { -fprintf (stderr,"Error: \"%s\" may be inet address, but it is not allowed in this context.\n" , arg); -exit (1 ); - }if (get_addr_1 (dst, arg, family)) {fprintf (stderr,"Error: an inet address is expected rather than \"%s\".\n" , arg);exit (1 );
@@ -638,6 +647,8 @@ const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflenmemcpy (dna.a_addr, addr,2 );return dnet_ntop (af, &dna, buf, buflen); } +case AF_PACKET : +return ll_addr_n2a (addr, len,ARPHRD_VOID , buf, buflen);default :return "???" ; }
Signature · 1 line
2.2.1
PATCH 4/8 iproute2: Add address family to/from string helper functions.
In reply to Eric W. BiedermanAdd the functions family_name and read_family to convert an address family to a string and to convernt a string to an address family.
--- include/utils.h | 3 +++ ip/ip.c | 16 +++------------- lib/utils.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 13 deletions(-)
include/utils.h +3 -0
@@ -106,6 +106,9 @@ extern const char *format_host(int af, int len, const void *addr,extern const char *rt_addr_n2a (int af,int len,const void *addr,char *buf,int buflen); +extern int read_family (const char *name); +extern const char *family_name (int family); +void missarg (const char *) __attribute__((noreturn));void invarg (const char *,const char *) __attribute__((noreturn));void duparg (const char *,const char *) __attribute__((noreturn));
ip/ip.c +3 -13
@@ -190,21 +190,11 @@ int main(int argc, char **argv) argv++;if (argc <=1 )usage (); -if (strcmp (argv[1 ],"inet" ) ==0 ) - preferred_family =AF_INET ; -else if (strcmp (argv[1 ],"inet6" ) ==0 ) - preferred_family =AF_INET6 ; -else if (strcmp (argv[1 ],"dnet" ) ==0 ) - preferred_family = AF_DECnet; -else if (strcmp (argv[1 ],"link" ) ==0 ) - preferred_family =AF_PACKET ; -else if (strcmp (argv[1 ],"ipx" ) ==0 ) - preferred_family =AF_IPX ; -else if (strcmp (argv[1 ],"bridge" ) ==0 ) - preferred_family =AF_BRIDGE ; -else if (strcmp (argv[1 ],"help" ) ==0 ) +if (strcmp (argv[1 ],"help" ) ==0 )usage ();else + preferred_family =read_family (argv[1 ]); +if (preferred_family ==AF_UNSPEC )invarg ("invalid protocol family" , argv[1 ]); }else if (strcmp (opt,"-4" ) ==0 ) { preferred_family =AF_INET ;
lib/utils.c +35 -0
@@ -654,6 +654,41 @@ const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflen } } +int read_family (const char *name) +{ +int family =AF_UNSPEC ; +if (strcmp (name,"inet" ) ==0 ) + family =AF_INET ; +else if (strcmp (name,"inet6" ) ==0 ) + family =AF_INET6 ; +else if (strcmp (name,"dnet" ) ==0 ) + family = AF_DECnet; +else if (strcmp (name,"link" ) ==0 ) + family =AF_PACKET ; +else if (strcmp (name,"ipx" ) ==0 ) + family =AF_IPX ; +else if (strcmp (name,"bridge" ) ==0 ) + family =AF_BRIDGE ; +return family; +} + +const char *family_name (int family) +{ +if (family ==AF_INET ) +return "inet" ; +if (family ==AF_INET6 ) +return "inet6" ; +if (family == AF_DECnet) +return "dnet" ; +if (family ==AF_PACKET ) +return "link" ; +if (family ==AF_IPX ) +return "ipx" ; +if (family ==AF_BRIDGE ) +return "bridge" ; +return "???" ; +} +#ifdef RESOLVE_HOSTNAMES struct namerec {
Signature · 1 line
2.2.1
PATCH 5/8 iproute2: misc whitespace cleanup
In reply to Eric W. BiedermanThis removes an extra space and causes things to line up.
--- ip/iptunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ip/iptunnel.c +1 -1
@@ -342,7 +342,7 @@ static void print_tunnel(struct ip_tunnel_parm *p)printf ("%s: %s/ip remote %s local %s " , p->name,tnl_strproto (p->iph.protocol), - p->iph.daddr ?format_host (AF_INET ,4 , &p->iph.daddr, s1,sizeof (s1)) :"any" , + p->iph.daddr ?format_host (AF_INET ,4 , &p->iph.daddr, s1,sizeof (s1)) :"any" , p->iph.saddr ?rt_addr_n2a (AF_INET ,4 , &p->iph.saddr, s2,sizeof (s2)) :"any" );if (p->iph.protocol ==IPPROTO_IPV6 && (p->i_flags &SIT_ISATAP )) {
Signature · 1 line
2.2.1
PATCH 6/8 iproute2: Add support for RTA_VIA attributes
In reply to Eric W. BiedermanAdd support for the RTA_VIA attribute that specifies an address family as well as an address for the next hop gateway.
To make it easy to pass this reorder inet_prefix so that it's tail is a proper RTA_VIA attribute.
--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)
include/linux/rtnetlink.h +7 -0
@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , +RTA_VIA , __RTA_MAX };
@@ -344,6 +345,12 @@ struct rtnexthop {#define RTNH_SPACE (len) RTNH_ALIGN(RTNH_LENGTH(len))#define RTNH_DATA (rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) +/* RTA_VIA */ +struct rtvia { +__kernel_sa_family_t rtvia_family; +__u8 rtvia_addr[0 ]; +}; +/* RTM_CACHEINFO */ struct rta_cacheinfo {
include/utils.h +4 -3
@@ -50,10 +50,11 @@ extern void incomplete_command(void) __attribute__((noreturn));typedef struct { -__u8 family; -__u8 bytelen; +__u16 flags; +__u16 bytelen;__s16 bitlen; -__u32 flags; +/* These next two fields match rtvia */ +__u16 family;__u32 data[8 ]; }inet_prefix ;
ip/iproute.c +67 -9
138 lines not on this page · raw message
man/man8/ip-route.8.in +12 -6
@@ -81,13 +81,18 @@ replace " } " .ti -8 .IR NH " := [ " .B via -.IR ADDRESS " ] [ " +[ +.IR FAMILY " ] " ADDRESS " ] [ " .B dev .IR STRING " ] [ " .B weight .IR NUMBER " ] " NHFLAGS .ti -8 +.IR FAMILY " := [ " +.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]" + +.ti -8 .IR OPTIONS " := " FLAGS " [ " .B mtu .IR NUMBER " ] [ "
@@ -333,9 +338,10 @@ table by default. the output device name. .TP -.BI via " ADDRESS" -the address of the nexthop router. Actually, the sense of this field -depends on the route type. For normal +.BI via " [ FAMILY ] ADDRESS" +the address of the nexthop router, in the address family FAMILY. +Actually, the sense of this field depends on the route type. For +normal .B unicast routes it is either the true next hop router or, if it is a direct route installed in BSD compatibility mode, it can be a local address
@@ -472,7 +478,7 @@ is a complex value with its own syntax similar to the top level argument lists: .in +8 -.BI via " ADDRESS" +.BI via " [ FAMILY ] ADDRESS" - is the nexthop router. .sp
@@ -669,7 +675,7 @@ only list routes of this type. only list routes going via this device. .TP -.BI via " PREFIX" +.BI via " [ FAMILY ] PREFIX" only list routes going via the nexthop routers selected by .IR PREFIX "."
Signature · 1 line
2.2.1
PATCH 7/8 iproute2: Add support for the RTA_NEWDST attribute.
In reply to Eric W. BiedermanThis attribute is like RTA_DST except it specifies the destination address to place on a packet when it leaves the host. For ip based protocols this is destination NAT and not a common part of forwarding. For protocols like MPLS label swapping is something that typically happens on every hop.
There is likely to be a RTA_NEWSRC at some point so RTA_NEWDST is printed as "as to" and can be specified either as "as to" or just "as"
--- include/linux/rtnetlink.h | 1 + ip/iproute.c | 19 ++++++++++++++++++- man/man8/ip-route.8.in | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-)
include/linux/rtnetlink.h +1 -0
@@ -304,6 +304,7 @@ enum rtattr_type_t {RTA_MARK ,RTA_MFC_STATS ,RTA_VIA , +RTA_NEWDST , __RTA_MAX };
ip/iproute.c +18 -1
@@ -77,7 +77,7 @@ static void usage(void)fprintf (stderr,"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" );fprintf (stderr,"NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" );fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]" ); -fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n" ); +fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n" );fprintf (stderr," [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n" );fprintf (stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n" );fprintf (stderr," [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n" );
@@ -402,6 +402,13 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) }else if (r->rtm_src_len) {fprintf (fp,"from 0/%u " , r->rtm_src_len); } +if (tb[RTA_NEWDST ]) { +fprintf (fp,"as to %s " ,format_host (r->rtm_family, +RTA_PAYLOAD (tb[RTA_NEWDST ]), +RTA_DATA (tb[RTA_NEWDST ]), + abuf,sizeof (abuf)) + ); + }if (r->rtm_tos && filter.tosmask !=-1 ) {SPRINT_BUF (b1);fprintf (fp,"tos %s " ,rtnl_dsfield_n2a (r->rtm_tos, b1,sizeof (b1)));
@@ -814,6 +821,16 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)if (req.r.rtm_family ==AF_UNSPEC ) req.r.rtm_family = addr.family;addattr_l (&req.n,sizeof (req),RTA_PREFSRC , &addr.data, addr.bytelen); + }else if (strcmp (*argv,"as" ) ==0 ) { +inet_prefix addr; +NEXT_ARG (); +if (strcmp (*argv,"to" ) ==0 ) { +NEXT_ARG (); + } +get_addr (&addr, *argv, req.r.rtm_family); +if (req.r.rtm_family ==AF_UNSPEC ) + req.r.rtm_family = addr.family; +addattr_l (&req.n,sizeof (req),RTA_NEWDST , &addr.data, addr.bytelen); }else if (strcmp (*argv,"via" ) ==0 ) {inet_prefix addr;int family;
man/man8/ip-route.8.in +5 -0
@@ -98,6 +98,11 @@ replace " } " .IR NUMBER " ] [ " .B advmss .IR NUMBER " ] [ " +.B as +[ +.B to +] +.IR ADDRESS " ]" .B rtt .IR TIME " ] [ " .B rttvar
Signature · 1 line
2.2.1
PATCH 8/8 iproute2: Add basic mpls support to iproute
In reply to Eric W. Biederman- Pull in the uapi mpls.h
- Update rtnetlink.h to include the mpls rtnetlink notification multicast group.
- Define AF_MPLS in utils.h if it is not defined from elsewhere
as is done with AF_DECnet
The address syntax for multiple mpls labels is a complete invention. When I looked there seemed to be no wide spread convention for talking about an mpls label stack in text for. Sometimes people did:
"{ Label1, Label2, Label3 }", sometimes people would do:
"[ label3, label2, label1 ]", and most of the time label stacks were not explicitly shown at all.
The syntax I wound up using, so it would not have spaces and so it would visually distinct from other kinds of addresses is.
label1/label2/label3 Where label1 is the label at the top of the label stack and label3 is the label at the bottom on the label stack.
When there is a single label this matches what seems to be convention with other tools. Just print out the numeric value of the mpls label.
The netlink protocol for labels uses the on the wire format for a label stack. The ttl and traffic class are expected to be 0. Using the on the wire format is common and what happens with other address types. BGP when passing label stacks also uses this technique with the exception that the ttl byte is not included making each label in a BGP label stack 3 bytes instead of 4.
--- Makefile | 3 +++ include/linux/mpls.h | 34 +++++++++++++++++++++++++++ include/linux/rtnetlink.h | 2 ++ include/utils.h | 10 ++++++++ ip/ip.c | 4 +++- ip/ipmonitor.c | 3 +++ ip/iproute.c | 4 +++- lib/mpls_ntop.c | 48 +++++++++++++++++++++++++++++++++++++++ lib/mpls_pton.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ lib/utils.c | 31 +++++++++++++++++++++++-- man/man8/ip-route.8.in | 2 +- man/man8/ip.8 | 7 +++++- 12 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 include/linux/mpls.h create mode 100644 lib/mpls_ntop.c create mode 100644 lib/mpls_pton.c
Makefile +3 -0
@@ -26,6 +26,9 @@ ADDLIB+=dnet_ntop.o dnet_pton.o #options for ipx ADDLIB+=ipx_ntop.o ipx_pton.o +#options for mpls +ADDLIB+=mpls_ntop.o mpls_pton.o + CC = gcc HOSTCC = gcc DEFINES += -D_GNU_SOURCE
include/linux/mpls.h new file +34 -0
@@ -0,0 +1,34 @@ +#ifndef _UAPI_MPLS_H +#define _UAPI_MPLS_H + +#include <linux/types.h> +#include <asm/byteorder.h> + +/* Reference: RFC 5462, RFC 3032 +* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | Label | TC |S| TTL | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* +* Label: Label Value, 20 bits +* TC: Traffic Class field, 3 bits +* S: Bottom of Stack, 1 bit +* TTL: Time to Live, 8 bits +*/ + +struct mpls_label { +__be32 entry; +}; + +#define MPLS_LS_LABEL_MASK 0xFFFFF000 +#define MPLS_LS_LABEL_SHIFT 12 +#define MPLS_LS_TC_MASK 0x00000E00 +#define MPLS_LS_TC_SHIFT 9 +#define MPLS_LS_S_MASK 0x00000100 +#define MPLS_LS_S_SHIFT 8 +#define MPLS_LS_TTL_MASK 0x000000FF +#define MPLS_LS_TTL_SHIFT 0 + +#endif /* _UAPI_MPLS_H */
include/linux/rtnetlink.h +2 -0
@@ -629,6 +629,8 @@ enum rtnetlink_groups {#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF RTNLGRP_MDB,#define RTNLGRP_MDB RTNLGRP_MDB + RTNLGRP_MPLS_ROUTE, +#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE __RTNLGRP_MAX };#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
include/utils.h +10 -0
@@ -78,6 +78,13 @@ struct ipx_addr {u_int8_t ipx_node[IPX_NODE_LEN ]; }; +#ifndef AF_MPLS +# define AF_MPLS 28 +#endif + +/* Maximum number of labels the mpls helpers support */ +#define MPLS_MAX_LABELS 8 +extern __u32 get_addr32 (const char *name);extern int get_addr_1 (inet_prefix *dst,const char *arg,int family);extern int get_prefix_1 (inet_prefix *dst,char *arg,int family);
@@ -123,6 +130,9 @@ int dnet_pton(int af, const char *src, void *addr);const char *ipx_ntop (int af,const void *addr,char *str,size_t len);int ipx_pton (int af,const char *src,void *addr); +const char *mpls_ntop (int af,const void *addr,char *str,size_t len); +int mpls_pton (int af,const char *src,void *addr); +extern int __iproute2_hz_internal;extern int __get_hz (void );
ip/ip.c +3 -1
@@ -52,7 +52,7 @@ static void usage(void)" netns | l2tp | fou | tcp_metrics | token | netconf }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -h[uman-readable] | -iec |\n" -" -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n" +" -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n" " -4 | -6 | -I | -D | -B | -0 |\n" " -l[oops] { maximum-addr-flush-attempts } |\n" " -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
@@ -206,6 +206,8 @@ int main(int argc, char **argv) preferred_family =AF_IPX ; }else if (strcmp (opt,"-D" ) ==0 ) { preferred_family = AF_DECnet; + }else if (strcmp (opt,"-M" ) ==0 ) { + preferred_family =AF_MPLS ; }else if (strcmp (opt,"-B" ) ==0 ) { preferred_family =AF_BRIDGE ; } else if (matches(opt, "-human") == 0 ||
ip/ipmonitor.c +3 -0
@@ -158,6 +158,7 @@ int do_ipmonitor(int argc, char **argv) groups |=nl_mgrp (RTNLGRP_IPV6_IFADDR ); groups |=nl_mgrp (RTNLGRP_IPV4_ROUTE ); groups |=nl_mgrp (RTNLGRP_IPV6_ROUTE ); + groups |=nl_mgrp (RTNLGRP_MPLS_ROUTE ); groups |=nl_mgrp (RTNLGRP_IPV4_MROUTE ); groups |=nl_mgrp (RTNLGRP_IPV6_MROUTE ); groups |=nl_mgrp (RTNLGRP_IPV6_PREFIX );
@@ -235,6 +236,8 @@ int do_ipmonitor(int argc, char **argv) groups |=nl_mgrp (RTNLGRP_IPV4_ROUTE );if (!preferred_family || preferred_family ==AF_INET6 ) groups |=nl_mgrp (RTNLGRP_IPV6_ROUTE ); +if (!preferred_family || preferred_family ==AF_MPLS ) + groups |=nl_mgrp (RTNLGRP_MPLS_ROUTE ); }if (lmroute) {if (!preferred_family || preferred_family ==AF_INET )
ip/iproute.c +3 -1
@@ -76,7 +76,7 @@ static void usage(void)fprintf (stderr," [ scope SCOPE ] [ metric METRIC ]\n" );fprintf (stderr,"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" );fprintf (stderr,"NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" ); -fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]" ); +fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]" );fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n" );fprintf (stderr," [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n" );fprintf (stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n" );
@@ -292,6 +292,8 @@ static int calc_host_len(const struct rtmsg *r)return 16 ; else if (r->rtm_family == AF_IPX) return 80; + else if (r->rtm_family == AF_MPLS) + return 20; else return -1; }
lib/mpls_ntop.c new file +48 -0
48 lines not on this page · raw message
lib/mpls_pton.c new file +58 -0
58 lines not on this page · raw message
lib/utils.c +29 -2
@@ -26,6 +26,7 @@#include <linux/pkt_sched.h> #include <linux/param.h> #include <linux/if_arp.h> +#include <linux/mpls.h> #include <time.h> #include <sys/time.h> #include <errno.h>
@@ -390,7 +391,7 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)if (strcmp (name,"default" ) ==0 ||strcmp (name,"all" ) ==0 ||strcmp (name,"any" ) ==0 ) { -if (family == AF_DECnet) +if ((family == AF_DECnet) || (family ==AF_MPLS ))return -1 ; addr->family = family; addr->bytelen = (family ==AF_INET6 ?16 :4 );
@@ -432,6 +433,23 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)return 0 ; } +if (family ==AF_MPLS ) { +int i; + addr->family =AF_MPLS ; +if (mpls_pton (AF_MPLS , name, addr->data) <=0 ) +return -1 ; + addr->bytelen =4 ; + addr->bitlen =20 ; +/* How many bytes do I need? */ +for (i =0 ; i <8 ; i++) { +if (ntohl (addr->data[i]) &MPLS_LS_S_MASK ) { + addr->bytelen = (i +1 )*4 ; +break ; + } + } +return 0 ; + } + addr->family =AF_INET ;if (family !=AF_UNSPEC && family !=AF_INET )return -1 ;
@@ -455,7 +473,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)if (strcmp (arg,"default" ) ==0 ||strcmp (arg,"any" ) ==0 ||strcmp (arg,"all" ) ==0 ) { -if (family == AF_DECnet) +if ((family == AF_DECnet) || (family =AF_MPLS ))return -1 ; dst->family = family; dst->bytelen =0 ;
@@ -476,6 +494,9 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)case AF_DECnet: dst->bitlen =16 ;break ; +case AF_MPLS : + dst->bitlen =20 ; +break ;default :case AF_INET : dst->bitlen =32 ;
@@ -639,6 +660,8 @@ const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflencase AF_INET :case AF_INET6 :return inet_ntop (af, addr, buf, buflen); +case AF_MPLS : +return mpls_ntop (af, addr, buf, buflen);case AF_IPX :return ipx_ntop (af, addr, buf, buflen);case AF_DECnet:
@@ -667,6 +690,8 @@ int read_family(const char *name) family =AF_PACKET ; else if (strcmp(name, "ipx") == 0) family =AF_IPX ; + else if (strcmp(name, "mpls") == 0) + family =AF_MPLS ; else if (strcmp(name, "bridge") == 0) family =AF_BRIDGE ;return family;
@@ -684,6 +709,8 @@ const char *family_name(int family)return "link" ;if (family ==AF_IPX )return "ipx" ; +if (family ==AF_MPLS ) +return "mpls" ;if (family ==AF_BRIDGE )return "bridge" ;return "???" ;
man/man8/ip-route.8.in +1 -1
@@ -90,7 +90,7 @@ replace " } " .ti -8 .IR FAMILY " := [ " -.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]" +.BR inet " | " inet6 " | " ipx " | " dnet " | " mpls " | " bridge " | " link " ]" .ti -8 .IR OPTIONS " := " FLAGS " [ "
man/man8/ip.8 +6 -1
@@ -73,7 +73,7 @@ Zero (0) means loop until all addresses are removed. .TP .BR "\-f" , " \-family " <FAMILY> Specifies the protocol family to use. The protocol family identifier can be one of -.BR "inet" , " inet6" , " bridge" , " ipx" , " dnet" +.BR "inet" , " inet6" , " bridge" , " ipx" , " dnet" , " mpls" or .BR link . If this option is not present,
@@ -115,6 +115,11 @@ shortcut for .BR "\-family ipx" . .TP +.B \-M +shortcut for +.BR "\-family mpls" . + +.TP .B \-0 shortcut for .BR "\-family link" .
Signature · 1 line
2.2.1
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH net-next 1/8] iproute2: Add a source addres length parameter to rt_addr_n2a
Quoted 6 lines · On Fri, 13 Mar 2015 18:52:09 +0000 "Eric W. Biederman" <[email protected]>…
For some address families (like
AF_PACKET) it is helpful to have the length when printing the address.Signed-off-by "Eric W. Biederman" <[email protected]>
Recent changes to utils.h make this patch no longer apply cleanly. Please redo thanks.
Re: [PATCH net-next 1/8] iproute2: Add a source addres length parameter to rt_addr_n2a
Quoted 4 lines · Stephen Hemminger
Quoted 1 line · On Fri, 13 Mar 2015 18:52:09 +0000 "Eric W. Biederman" <[email protected]>…
Quoted 8 lines
Quoted 5 lines
For some address families (like
AF_PACKET) it is helpful to have the length when printing the address.Signed-off-by "Eric W. Biederman" <[email protected]>Recent changes to
utils.hmake this patch no longer apply cleanly. Please redo thanks.
Yeah the change to introduce af_bitlen does naturally cause some conflicts. I will fix things up and resend.
Patch application races are a pain.
Eric
cover iproute2: MPLS support (now with af_bit_len)
This set of changes adds support for nexthops in different address families, with the new netlink RTA_VIA option.
Support is added for routes that change the destination address (as MPLS does) with the RTA_NEWDST attribute.
Support for MPLS addresses is added (for multiple labels I had to make up the syntax I used label/label/label as it fits in well with addresses that don't have a space in them).
Support for these options is merged into David's net-next kernel tree, and the meaning of the options is unlikely to change in any significant way before this code merges upstream.
The documentation has been updated to report that the new options are present and to report roughly what they do. This includes ip --help and the man pages.
Eric W. Biederman (8):
iproute2: Add a source addres length parameter to rt_addr_n2a
iproute2: Make the addr argument of ll_addr_n2a const
iproute2: Add support for printing AF_PACKET addresses
iproute2: Add address family to/from string helper functions.
iproute2: misc whitespace cleanup
iproute2: Add support for RTA_VIA attributes
iproute2: Add support for the RTA_NEWDST attribute.
iproute2: Add basic mpls support to iproute
Makefile | 3 ++ include/linux/mpls.h | 34 +++++++++++++++ include/linux/rtnetlink.h | 10 +++++ include/rt_names.h | 2 +- include/utils.h | 22 ++++++++-- ip/ip.c | 20 +++------ ip/iplink_bond.c | 1 + ip/ipmonitor.c | 3 ++ ip/ipmroute.c | 2 + ip/ipprefix.c | 4 +- ip/iproute.c | 106 ++++++++++++++++++++++++++++++++++++++++------ ip/iprule.c | 10 +++-- ip/iptunnel.c | 4 +- ip/ipxfrm.c | 17 +++++--- ip/link_ip6tnl.c | 2 + ip/xfrm_monitor.c | 8 ++-- lib/ll_addr.c | 2 +- lib/mpls_ntop.c | 48 +++++++++++++++++++++ lib/mpls_pton.c | 58 +++++++++++++++++++++++++ lib/utils.c | 90 +++++++++++++++++++++++++++++++++++---- man/man8/ip-route.8.in | 23 +++++++--- man/man8/ip.8 | 7 ++- 22 files changed, 410 insertions(+), 66 deletions(-)
PATCH 1/8 iproute2: Add a source addres length parameter to rt_addr_n2a
For some address families (like AF_PACKET) it is helpful to have the length when prenting the address.
--- include/utils.h | 2 +- ip/iplink_bond.c | 1 + ip/ipmroute.c | 2 ++ ip/ipprefix.c | 4 +++- ip/iproute.c | 11 +++++++---- ip/iprule.c | 10 ++++++---- ip/iptunnel.c | 2 +- ip/ipxfrm.c | 17 +++++++++++------ ip/link_ip6tnl.c | 2 ++ ip/xfrm_monitor.c | 8 +++++--- lib/utils.c | 4 ++-- 11 files changed, 41 insertions(+), 22 deletions(-)
include/utils.h +1 -1
@@ -106,7 +106,7 @@ extern int af_byte_len(int af);extern const char *format_host (int af,int len,const void *addr,char *buf,int buflen); -extern const char *rt_addr_n2a (int af,const void *addr, +extern const char *rt_addr_n2a (int af,int len,const void *addr,char *buf,int buflen);void missarg (const char *) __attribute__((noreturn));
ip/iplink_bond.c +1 -0
@@ -415,6 +415,7 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])if (iptb[i])fprintf (f,"%s" ,rt_addr_n2a (AF_INET , +RTA_PAYLOAD (iptb[i]),RTA_DATA (iptb[i]), buf,INET_ADDRSTRLEN ));
ip/ipmroute.c +2 -0
@@ -116,6 +116,7 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_SRC ]) len =snprintf (obuf,sizeof (obuf),"(%s, " ,rt_addr_n2a (family, +RTA_PAYLOAD (tb[RTA_SRC ]),RTA_DATA (tb[RTA_SRC ]), abuf,sizeof (abuf)));else
@@ -123,6 +124,7 @@ int print_mroute(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_DST ])snprintf (obuf + len,sizeof (obuf) - len,"%s)" ,rt_addr_n2a (family, +RTA_PAYLOAD (tb[RTA_DST ]),RTA_DATA (tb[RTA_DST ]), abuf,sizeof (abuf)));else
ip/ipprefix.c +3 -1
@@ -80,7 +80,9 @@ int print_prefix(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) pfx = (struct in6_addr *)RTA_DATA (tb[PREFIX_ADDRESS ]);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"%s" ,rt_addr_n2a (family, pfx, +fprintf (fp,"%s" ,rt_addr_n2a (family, +RTA_PAYLOAD (tb[PREFIX_ADDRESS ]), + pfx, abuf,sizeof (abuf))); }fprintf (fp,"/%u " , prefix->prefix_len);
ip/iproute.c +7 -4
@@ -339,8 +339,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_DST ]) {if (r->rtm_dst_len != host_len) {fprintf (fp,"%s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[RTA_DST ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[RTA_DST ]), +RTA_DATA (tb[RTA_DST ]), + abuf,sizeof (abuf)), r->rtm_dst_len ); }else {
@@ -358,8 +359,9 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[RTA_SRC ]) {if (r->rtm_src_len != host_len) {fprintf (fp,"from %s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[RTA_SRC ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[RTA_SRC ]), +RTA_DATA (tb[RTA_SRC ]), + abuf,sizeof (abuf)), r->rtm_src_len ); }else {
@@ -401,6 +403,7 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)*/ fprintf (fp," src %s " ,rt_addr_n2a (r->rtm_family, +RTA_PAYLOAD (tb[RTA_PREFSRC ]),RTA_DATA (tb[RTA_PREFSRC ]), abuf,sizeof (abuf))); }
ip/iprule.c +6 -4
@@ -82,8 +82,9 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[FRA_SRC ]) {if (r->rtm_src_len != host_len) {fprintf (fp,"from %s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[FRA_SRC ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[FRA_SRC ]), +RTA_DATA (tb[FRA_SRC ]), + abuf,sizeof (abuf)), r->rtm_src_len ); }else {
@@ -102,8 +103,9 @@ int print_rule(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)if (tb[FRA_DST ]) {if (r->rtm_dst_len != host_len) {fprintf (fp,"to %s/%u " ,rt_addr_n2a (r->rtm_family, -RTA_DATA (tb[FRA_DST ]), - abuf,sizeof (abuf)), +RTA_PAYLOAD (tb[FRA_DST ]), +RTA_DATA (tb[FRA_DST ]), + abuf,sizeof (abuf)), r->rtm_dst_len ); }else {
ip/iptunnel.c +1 -1
@@ -343,7 +343,7 @@ static void print_tunnel(struct ip_tunnel_parm *p) p->name,tnl_strproto (p->iph.protocol), p->iph.daddr ?format_host (AF_INET ,4 , &p->iph.daddr, s1,sizeof (s1)) :"any" , - p->iph.saddr ? rt_addr_n2a(AF_INET, &p->iph.saddr, s2, sizeof(s2)) : "any"); + p->iph.saddr ? rt_addr_n2a(AF_INET, 4, &p->iph.saddr, s2, sizeof(s2)) : "any");if (p->iph.protocol ==IPPROTO_IPV6 && (p->i_flags &SIT_ISATAP )) {struct ip_tunnel_prl prl[16 ];
ip/ipxfrm.c +11 -6
@@ -288,10 +288,10 @@ void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id,fputs (title, fp);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"src %s " ,rt_addr_n2a (family, +fprintf (fp,"src %s " ,rt_addr_n2a (family,sizeof (*saddr), saddr, abuf,sizeof (abuf)));memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"dst %s" ,rt_addr_n2a (family, +fprintf (fp,"dst %s" ,rt_addr_n2a (family,sizeof (id->daddr), &id->daddr, abuf,sizeof (abuf)));fprintf (fp,"%s" , _SL_);
@@ -455,11 +455,15 @@ void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,fputs (prefix, fp);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"src %s/%u " ,rt_addr_n2a (f, &sel->saddr, abuf,sizeof (abuf)), +fprintf (fp,"src %s/%u " , +rt_addr_n2a (f,sizeof (sel->saddr), &sel->saddr, + abuf,sizeof (abuf)), sel->prefixlen_s);memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"dst %s/%u " ,rt_addr_n2a (f, &sel->daddr, abuf,sizeof (abuf)), +fprintf (fp,"dst %s/%u " , +rt_addr_n2a (f,sizeof (sel->daddr), &sel->daddr, + abuf,sizeof (abuf)), sel->prefixlen_d);if (sel->proto)
@@ -754,7 +758,8 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,memset (abuf,'\0' ,sizeof (abuf));fprintf (fp,"addr %s" , -rt_addr_n2a (family, &e->encap_oa, abuf,sizeof (abuf))); +rt_addr_n2a (family,sizeof (e->encap_oa), &e->encap_oa, + abuf,sizeof (abuf)));fprintf (fp,"%s" , _SL_); }
@@ -782,7 +787,7 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,memset (abuf,'\0' ,sizeof (abuf));fprintf (fp,"%s" , -rt_addr_n2a (family, coa, +rt_addr_n2a (family,sizeof (*coa), coa, abuf,sizeof (abuf)));fprintf (fp,"%s" , _SL_); }
ip/link_ip6tnl.c +2 -0
@@ -285,6 +285,7 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tbif (tb[IFLA_IPTUN_REMOTE ]) {fprintf (f,"remote %s " ,rt_addr_n2a (AF_INET6 , +RTA_PAYLOAD (tb[IFLA_IPTUN_REMOTE ]),RTA_DATA (tb[IFLA_IPTUN_REMOTE ]), s1,sizeof (s1))); }
@@ -292,6 +293,7 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tbif (tb[IFLA_IPTUN_LOCAL ]) {fprintf (f,"local %s " ,rt_addr_n2a (AF_INET6 , +RTA_PAYLOAD (tb[IFLA_IPTUN_LOCAL ]),RTA_DATA (tb[IFLA_IPTUN_LOCAL ]), s1,sizeof (s1))); }
ip/xfrm_monitor.c +5 -3
@@ -227,7 +227,8 @@ static void xfrm_usersa_print(const struct xfrm_usersa_id *sa_id, __u32 reqid, F buf[0 ] =0 ;fprintf (fp,"dst %s " , -rt_addr_n2a (sa_id->family, &sa_id->daddr, buf,sizeof (buf))); +rt_addr_n2a (sa_id->family,sizeof (sa_id->daddr), &sa_id->daddr, + buf,sizeof (buf)));fprintf (fp," reqid 0x%x" , reqid);
@@ -246,7 +247,8 @@ static int xfrm_ae_print(const struct sockaddr_nl *who,xfrm_ae_flags_print (id->flags, arg);fprintf (fp,"\n\t" );memset (abuf,'\0' ,sizeof (abuf)); -fprintf (fp,"src %s " ,rt_addr_n2a (id->sa_id.family, &id->saddr, +fprintf (fp,"src %s " ,rt_addr_n2a (id->sa_id.family, +sizeof (id->saddr), &id->saddr, abuf,sizeof (abuf)));xfrm_usersa_print (&id->sa_id, id->reqid, fp);
@@ -262,7 +264,7 @@ static void xfrm_print_addr(FILE *fp, int family, xfrm_address_t *a)char buf[256 ]; buf[0 ] =0 ; -fprintf (fp,"%s" ,rt_addr_n2a (family, a, buf,sizeof (buf))); +fprintf (fp,"%s" ,rt_addr_n2a (family,sizeof (*a), a, buf,sizeof (buf))); } static int xfrm_mapping_print(const struct sockaddr_nl *who,
lib/utils.c +2 -2
@@ -636,7 +636,7 @@ int __get_user_hz(void)return sysconf (_SC_CLK_TCK); } -const char *rt_addr_n2a (int af,const void *addr,char *buf,int buflen) +const char *rt_addr_n2a (int af,int len,const void *addr,char *buf,int buflen) {switch (af) {case AF_INET :
@@ -723,7 +723,7 @@ const char *format_host(int af, int len, const void *addr, return n; }#endif -return rt_addr_n2a (af, addr, buf, buflen); +return rt_addr_n2a (af, len, addr, buf, buflen); }
Signature · 1 line
2.2.1
PATCH 2/8 iproute2: Make the addr argument of ll_addr_n2a const
In reply to Eric W. BiedermanThis avoids build warnings when AF_PACKET support is added to rt_addr_n2a.
--- include/rt_names.h | 2 +- lib/ll_addr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/rt_names.h +1 -1
@@ -22,7 +22,7 @@ int inet_proto_a2n(const char *buf);const char *ll_type_n2a (int type,char *buf,int len); -const char *ll_addr_n2a (unsigned char *addr,int alen, +const char *ll_addr_n2a (const unsigned char *addr,int alen,int type,char *buf,int blen);int ll_addr_a2n (char *lladdr,int len,const char *arg);
lib/ll_addr.c +1 -1
@@ -29,7 +29,7 @@#include "utils.h" -const char *ll_addr_n2a (unsigned char *addr,int alen,int type,char *buf,int blen) +const char *ll_addr_n2a (const unsigned char *addr,int alen,int type,char *buf,int blen) {int i;int l;
Signature · 1 line
2.2.1
PATCH 3/8 iproute2: Add support for printing AF_PACKET addresses
In reply to Eric W. Biederman--- lib/utils.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
lib/utils.c +16 -5
@@ -25,11 +25,12 @@#include <asm/types.h> #include <linux/pkt_sched.h> #include <linux/param.h> +#include <linux/if_arp.h> #include <time.h> #include <sys/time.h> #include <errno.h> - +#include "rt_names.h" #include "utils.h" #include "namespace.h"
@@ -397,6 +398,18 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)return 0 ; } +if (family ==AF_PACKET ) { +int len; + len =ll_addr_a2n ((char *)&addr->data,sizeof (addr->data), name); +if (len <0 ) +return -1 ; + + addr->family =AF_PACKET ; + addr->bytelen = len; + addr->bitlen = len *8 ; +return 0 ; + } +if (strchr (name,':' )) { addr->family =AF_INET6 ;if (family !=AF_UNSPEC && family !=AF_INET6 )
@@ -497,10 +510,6 @@ done:int get_addr (inet_prefix *dst,const char *arg,int family) { -if (family ==AF_PACKET ) { -fprintf (stderr,"Error: \"%s\" may be inet address, but it is not allowed in this context.\n" , arg); -exit (1 ); - }if (get_addr_1 (dst, arg, family)) {fprintf (stderr,"Error: an inet address is expected rather than \"%s\".\n" , arg);exit (1 );
@@ -650,6 +659,8 @@ const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflenmemcpy (dna.a_addr, addr,2 );return dnet_ntop (af, &dna, buf, buflen); } +case AF_PACKET : +return ll_addr_n2a (addr, len,ARPHRD_VOID , buf, buflen);default :return "???" ; }
Signature · 1 line
2.2.1
PATCH 4/8 iproute2: Add address family to/from string helper functions.
In reply to Eric W. BiedermanAdd the functions family_name and read_family to convert an address family to a string and to convernt a string to an address family.
--- include/utils.h | 3 +++ ip/ip.c | 16 +++------------- lib/utils.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 13 deletions(-)
include/utils.h +3 -0
@@ -109,6 +109,9 @@ extern const char *format_host(int af, int len, const void *addr,extern const char *rt_addr_n2a (int af,int len,const void *addr,char *buf,int buflen); +extern int read_family (const char *name); +extern const char *family_name (int family); +void missarg (const char *) __attribute__((noreturn));void invarg (const char *,const char *) __attribute__((noreturn));void duparg (const char *,const char *) __attribute__((noreturn));
ip/ip.c +3 -13
@@ -190,21 +190,11 @@ int main(int argc, char **argv) argv++;if (argc <=1 )usage (); -if (strcmp (argv[1 ],"inet" ) ==0 ) - preferred_family =AF_INET ; -else if (strcmp (argv[1 ],"inet6" ) ==0 ) - preferred_family =AF_INET6 ; -else if (strcmp (argv[1 ],"dnet" ) ==0 ) - preferred_family = AF_DECnet; -else if (strcmp (argv[1 ],"link" ) ==0 ) - preferred_family =AF_PACKET ; -else if (strcmp (argv[1 ],"ipx" ) ==0 ) - preferred_family =AF_IPX ; -else if (strcmp (argv[1 ],"bridge" ) ==0 ) - preferred_family =AF_BRIDGE ; -else if (strcmp (argv[1 ],"help" ) ==0 ) +if (strcmp (argv[1 ],"help" ) ==0 )usage ();else + preferred_family =read_family (argv[1 ]); +if (preferred_family ==AF_UNSPEC )invarg ("invalid protocol family" , argv[1 ]); }else if (strcmp (opt,"-4" ) ==0 ) { preferred_family =AF_INET ;
lib/utils.c +35 -0
@@ -666,6 +666,41 @@ const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflen } } +int read_family (const char *name) +{ +int family =AF_UNSPEC ; +if (strcmp (name,"inet" ) ==0 ) + family =AF_INET ; +else if (strcmp (name,"inet6" ) ==0 ) + family =AF_INET6 ; +else if (strcmp (name,"dnet" ) ==0 ) + family = AF_DECnet; +else if (strcmp (name,"link" ) ==0 ) + family =AF_PACKET ; +else if (strcmp (name,"ipx" ) ==0 ) + family =AF_IPX ; +else if (strcmp (name,"bridge" ) ==0 ) + family =AF_BRIDGE ; +return family; +} + +const char *family_name (int family) +{ +if (family ==AF_INET ) +return "inet" ; +if (family ==AF_INET6 ) +return "inet6" ; +if (family == AF_DECnet) +return "dnet" ; +if (family ==AF_PACKET ) +return "link" ; +if (family ==AF_IPX ) +return "ipx" ; +if (family ==AF_BRIDGE ) +return "bridge" ; +return "???" ; +} +#ifdef RESOLVE_HOSTNAMES struct namerec {
Signature · 1 line
2.2.1
PATCH 5/8 iproute2: misc whitespace cleanup
In reply to Eric W. Biederman--- ip/iptunnel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ip/iptunnel.c +1 -1
@@ -342,7 +342,7 @@ static void print_tunnel(struct ip_tunnel_parm *p)printf ("%s: %s/ip remote %s local %s " , p->name,tnl_strproto (p->iph.protocol), - p->iph.daddr ?format_host (AF_INET ,4 , &p->iph.daddr, s1,sizeof (s1)) :"any" , + p->iph.daddr ?format_host (AF_INET ,4 , &p->iph.daddr, s1,sizeof (s1)) :"any" , p->iph.saddr ?rt_addr_n2a (AF_INET ,4 , &p->iph.saddr, s2,sizeof (s2)) :"any" );if (p->iph.protocol ==IPPROTO_IPV6 && (p->i_flags &SIT_ISATAP )) {
Signature · 1 line
2.2.1
PATCH 6/8 iproute2: Add support for the RTA_VIA attribute
In reply to Eric W. BiedermanAdd support for the RTA_VIA attribute that specifies an address family as well as an address for the next hop gateway.
To make it easy to pass this reorder inet_prefix so that it's tail is a proper RTA_VIA attribute.
--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)
include/linux/rtnetlink.h +7 -0
@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , +RTA_VIA , __RTA_MAX };
@@ -344,6 +345,12 @@ struct rtnexthop {#define RTNH_SPACE (len) RTNH_ALIGN(RTNH_LENGTH(len))#define RTNH_DATA (rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) +/* RTA_VIA */ +struct rtvia { +__kernel_sa_family_t rtvia_family; +__u8 rtvia_addr[0 ]; +}; +/* RTM_CACHEINFO */ struct rta_cacheinfo {
include/utils.h +4 -3
@@ -50,10 +50,11 @@ extern void incomplete_command(void) __attribute__((noreturn));typedef struct { -__u8 family; -__u8 bytelen; +__u16 flags; +__u16 bytelen;__s16 bitlen; -__u32 flags; +/* These next two fields match rtvia */ +__u16 family;__u32 data[8 ]; }inet_prefix ;
ip/iproute.c +67 -9
138 lines not on this page · raw message
man/man8/ip-route.8.in +12 -6
@@ -81,13 +81,18 @@ replace " } " .ti -8 .IR NH " := [ " .B via -.IR ADDRESS " ] [ " +[ +.IR FAMILY " ] " ADDRESS " ] [ " .B dev .IR STRING " ] [ " .B weight .IR NUMBER " ] " NHFLAGS .ti -8 +.IR FAMILY " := [ " +.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]" + +.ti -8 .IR OPTIONS " := " FLAGS " [ " .B mtu .IR NUMBER " ] [ "
@@ -333,9 +338,10 @@ table by default. the output device name. .TP -.BI via " ADDRESS" -the address of the nexthop router. Actually, the sense of this field -depends on the route type. For normal +.BI via " [ FAMILY ] ADDRESS" +the address of the nexthop router, in the address family FAMILY. +Actually, the sense of this field depends on the route type. For +normal .B unicast routes it is either the true next hop router or, if it is a direct route installed in BSD compatibility mode, it can be a local address
@@ -472,7 +478,7 @@ is a complex value with its own syntax similar to the top level argument lists: .in +8 -.BI via " ADDRESS" +.BI via " [ FAMILY ] ADDRESS" - is the nexthop router. .sp
@@ -669,7 +675,7 @@ only list routes of this type. only list routes going via this device. .TP -.BI via " PREFIX" +.BI via " [ FAMILY ] PREFIX" only list routes going via the nexthop routers selected by .IR PREFIX "."
Signature · 1 line
2.2.1
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 19 lines · Eric W. Biederman
Add support for the
RTA_VIAattribute that specifies an address family as well as an address for the next hop gateway.To make it easy to pass this reorder
inet_prefixso that it's tail is a properRTA_VIAattribute.Signed-off-by "Eric W. Biederman" <[email protected]>--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)include/linux/rtnetlink.h +0
-0
include/linux/rtnetlink.h enum rtattr_type_t { · line 306
Quoted 4 lines
include/linux/rtnetlink.h +1
-0@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , + RTA_VIA,
eric, if its not too late, what do you think about renaming RTA_VIA attribute to RTA_NEWGATEWAY (similar to your new RTA_NEWDST attribute to specify a label dst) ?. RTA_VIA is fine too. This is indeed a new way to specify a gateway (and can/will be used by RFC 5549 in the future).
If there is interest in renaming it to RTA_NEWGATEWAY (or any other name, cant think of anything better right now), I will be happy to submit a follow-on patch.
Thanks!.
Quoted 242 lines
include/linux/rtnetlink.h +6
-0__RTA_MAX };@@ -344,6 +345,12 @@ struct rtnexthop {#define RTNH_SPACE (len) RTNH_ALIGN(RTNH_LENGTH(len))#define RTNH_DATA (rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) +/* RTA_VIA */ +struct rtvia { +__kernel_sa_family_t rtvia_family; +__u8 rtvia_addr[0 ]; +}; +/* RTM_CACHEINFO */ struct rta_cacheinfo {include/utils.h +4
-3@@ -50,10 +50,11 @@ extern void incomplete_command(void) __attribute__((noreturn));typedef struct { -__u8 family; -__u8 bytelen; +__u16 flags; +__u16 bytelen;__s16 bitlen; -__u32 flags; +/* These next two fields match rtvia */ +__u16 family;__u32 data[8 ]; }inet_prefix ;ip/iproute.c +67
-9@@ -75,7 +75,8 @@ static void usage(void)fprintf (stderr," [ table TABLE_ID ] [ proto RTPROTO ]\n" );fprintf (stderr," [ scope SCOPE ] [ metric METRIC ]\n" );fprintf (stderr,"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" ); -fprintf (stderr,"NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" ); +fprintf (stderr,"NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" ); +fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]" );fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n" );fprintf (stderr," [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n" );fprintf (stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n" );@@ -185,8 +186,15 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) (r->rtm_family != filter.msrc.family || (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))return 0 ; -if (filter.rvia.family && r->rtm_family != filter.rvia.family) -return 0 ; +if (filter.rvia.family) { +int family = r->rtm_family; +if (tb[RTA_VIA ]) { +struct rtvia *via =RTA_DATA (tb[RTA_VIA ]); + family = via->rtvia_family; + } +if (family != filter.rvia.family) +return 0 ; + }if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family)return 0 ;@@ -205,6 +213,12 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) via.family = r->rtm_family;if (tb[RTA_GATEWAY ])memcpy (&via.data,RTA_DATA (tb[RTA_GATEWAY ]), host_len/8 ); +if (tb[RTA_VIA ]) { +size_t len =RTA_PAYLOAD (tb[RTA_VIA ]) -2 ; +struct rtvia *rtvia =RTA_DATA (tb[RTA_VIA ]); + via.family = rtvia->rtvia_family; +memcpy (&via.data, rtvia->rtvia_addr, len); + } }if (filter.rprefsrc.bitlen>0 ) {memset (&prefsrc,0 ,sizeof (prefsrc));@@ -386,6 +400,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)RTA_DATA (tb[RTA_GATEWAY ]), abuf, sizeof(abuf))); } +if (tb[RTA_VIA ]) { +size_t len =RTA_PAYLOAD (tb[RTA_VIA ]) -2 ; +struct rtvia *via =RTA_DATA (tb[RTA_VIA ]); +fprintf (fp,"via %s %s " , +family_name (via->rtvia_family), +format_host (via->rtvia_family, len, via->rtvia_addr, + abuf,sizeof (abuf))); + }if (tb[RTA_OIF ] && filter.oifmask !=-1 )fprintf (fp,"dev %s " ,ll_index_to_name (*(int *)RTA_DATA (tb[RTA_OIF ])));@@ -601,6 +623,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)RTA_DATA (tb[RTA_GATEWAY ]), abuf, sizeof(abuf))); } +if (tb[RTA_VIA ]) { +size_t len =RTA_PAYLOAD (tb[RTA_VIA ]) -2 ; +struct rtvia *via =RTA_DATA (tb[RTA_VIA ]); +fprintf (fp,"via %s %s " , +family_name (via->rtvia_family), +format_host (via->rtvia_family, len, via->rtvia_addr, + abuf,sizeof (abuf))); + }if (tb[RTA_FLOW ]) {__u32 to =rta_getattr_u32 (tb[RTA_FLOW ]);__u32 from = to>>16 ;@@ -648,12 +678,23 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,while (++argv, --argc >0 ) {if (strcmp (*argv,"via" ) ==0 ) {inet_prefix addr; +int family;NEXT_ARG (); -get_addr (&addr, *argv, r->rtm_family); + family =read_family (*argv); +if (family ==AF_UNSPEC ) + family = r->rtm_family; +else +NEXT_ARG (); +get_addr (&addr, *argv, family);if (r->rtm_family ==AF_UNSPEC ) r->rtm_family = addr.family; -rta_addattr_l (rta,4096 ,RTA_GATEWAY , &addr.data, addr.bytelen); - rtnh->rtnh_len +=sizeof (struct rtattr ) + addr.bytelen; +if (addr.family == r->rtm_family) { +rta_addattr_l (rta,4096 ,RTA_GATEWAY , &addr.data, addr.bytelen); + rtnh->rtnh_len +=sizeof (struct rtattr ) + addr.bytelen; + }else { +rta_addattr_l (rta,4096 ,RTA_VIA , &addr.family, addr.bytelen+2 ); + rtnh->rtnh_len +=sizeof (struct rtattr ) + addr.bytelen+2 ; + } }else if (strcmp (*argv,"dev" ) ==0 ) {NEXT_ARG ();if ((rtnh->rtnh_ifindex =ll_name_to_index (*argv)) ==0 ) {@@ -761,12 +802,21 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)addattr_l (&req.n,sizeof (req),RTA_PREFSRC , &addr.data, addr.bytelen); }else if (strcmp (*argv,"via" ) ==0 ) {inet_prefix addr; +int family; gw_ok =1 ;NEXT_ARG (); -get_addr (&addr, *argv, req.r.rtm_family); + family =read_family (*argv); +if (family ==AF_UNSPEC ) + family = req.r.rtm_family; +else +NEXT_ARG (); +get_addr (&addr, *argv, family);if (req.r.rtm_family ==AF_UNSPEC ) req.r.rtm_family = addr.family; -addattr_l (&req.n,sizeof (req),RTA_GATEWAY , &addr.data, addr.bytelen); +if (addr.family == req.r.rtm_family) +addattr_l (&req.n,sizeof (req),RTA_GATEWAY , &addr.data, addr.bytelen); +else +addattr_l (&req.n,sizeof (req),RTA_VIA , &addr.family, addr.bytelen+2 ); }else if (strcmp (*argv,"from" ) ==0 ) {inet_prefix addr;NEXT_ARG ();@@ -1251,8 +1301,14 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)get_unsigned (&mark, *argv,0 ); filter.markmask =-1 ; }else if (strcmp (*argv,"via" ) ==0 ) { +int family;NEXT_ARG (); -get_prefix (&filter.rvia, *argv, do_ipv6); + family =read_family (*argv); +if (family ==AF_UNSPEC ) + family = do_ipv6; +else +NEXT_ARG (); +get_prefix (&filter.rvia, *argv, family); }else if (strcmp (*argv,"src" ) ==0 ) {NEXT_ARG ();get_prefix (&filter.rprefsrc, *argv, do_ipv6);@@ -1554,6 +1610,8 @@ static int iproute_get(int argc, char **argv) tb[RTA_OIF ]->rta_type =0 ;if (tb[RTA_GATEWAY ]) tb[RTA_GATEWAY ]->rta_type =0 ; +if (tb[RTA_VIA ]) + tb[RTA_VIA ]->rta_type =0 ;if (!idev && tb[RTA_IIF ]) tb[RTA_IIF ]->rta_type =0 ; req.n.nlmsg_flags =NLM_F_REQUEST ;man/man8/ip-route.8.in +12
-6@@ -81,13 +81,18 @@ replace " } " .ti -8 .IR NH " := [ " .B via -.IR ADDRESS " ] [ " +[ +.IR FAMILY " ] " ADDRESS " ] [ " .B dev .IR STRING " ] [ " .B weight .IR NUMBER " ] " NHFLAGS .ti -8 +.IR FAMILY " := [ " +.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]" + +.ti -8 .IR OPTIONS " := " FLAGS " [ " .B mtu .IR NUMBER " ] [ "@@ -333,9 +338,10 @@ table by default. the output device name. .TP -.BI via " ADDRESS" -the address of the nexthop router. Actually, the sense of this field -depends on the route type. For normal +.BI via " [ FAMILY ] ADDRESS" +the address of the nexthop router, in the address family FAMILY. +Actually, the sense of this field depends on the route type. For +normal .B unicast routes it is either the true next hop router or, if it is a direct route installed in BSD compatibility mode, it can be a local address@@ -472,7 +478,7 @@ is a complex value with its own syntax similar to the top level argument lists: .in +8 -.BI via " ADDRESS" +.BI via " [ FAMILY ] ADDRESS" - is the nexthop router. .sp@@ -669,7 +675,7 @@ only list routes of this type. only list routes going via this device. .TP -.BI via " PREFIX" +.BI via " [ FAMILY ] PREFIX" only list routes going via the nexthop routers selected by .IR PREFIX "."
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 32 lines · roopa
Quoted 19 lines · Eric W. Biederman
Add support for the
RTA_VIAattribute that specifies an address family as well as an address for the next hop gateway.To make it easy to pass this reorder
inet_prefixso that it's tail is a properRTA_VIAattribute.Signed-off-by "Eric W. Biederman" <[email protected]>--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)include/linux/rtnetlink.h +0
-0include/linux/rtnetlink.h enum rtattr_type_t { · line 306
Quoted 4 lines
include/linux/rtnetlink.h +1
-0@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , + RTA_VIA,eric, if its not too late, what do you think about renaming
RTA_VIAattribute toRTA_NEWGATEWAY(similar to your newRTA_NEWDSTattribute to specify a label dst) ?.RTA_VIAis fine too.
This is indeed a new way to specify a gateway (and can/will be used by RFC 5549 in the future).
Quoted 3 lines
If there is interest in renaming it to
RTA_NEWGATEWAY(or any other name, cant think of anything better right now),
I will be happy to submit a follow-on patch.
FWIW, I actually do not mind the name RTA_VIA. I was planning to replace use of RTA_GATEWAY in iproute2 and just usa RTA_VIA for all nexthops regardless of the address family of the dest route or nexthop and would allow easy creation of the infrastructure needed to support RFC5549 -- obviously while keeping backwards compatibility in the kernel.
This was what my orignal set did (not submitted to netdev, but discussed with others at netconf) and it was much cleaner code-wise (but not ideal as I overloaded the use of RTA_GATEWAY and that was not pleasing to me or others).
Quoted 233 lines
Thanks!.
Quoted 229 lines
include/linux/rtnetlink.h +6
-0__RTA_MAX };@@ -344,6 +345,12 @@ struct rtnexthop {#define RTNH_SPACE (len) RTNH_ALIGN(RTNH_LENGTH(len))#define RTNH_DATA (rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0))) +/* RTA_VIA */ +struct rtvia { +__kernel_sa_family_t rtvia_family; +__u8 rtvia_addr[0 ]; +}; +/* RTM_CACHEINFO */ struct rta_cacheinfo {include/utils.h +4
-3@@ -50,10 +50,11 @@ extern void incomplete_command(void) __attribute__((noreturn));typedef struct { -__u8 family; -__u8 bytelen; +__u16 flags; +__u16 bytelen;__s16 bitlen; -__u32 flags; +/* These next two fields match rtvia */ +__u16 family;__u32 data[8 ]; }inet_prefix ;ip/iproute.c +67
-9@@ -75,7 +75,8 @@ static void usage(void)fprintf (stderr," [ table TABLE_ID ] [ proto RTPROTO ]\n" );fprintf (stderr," [ scope SCOPE ] [ metric METRIC ]\n" );fprintf (stderr,"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" ); -fprintf (stderr,"NH := [ via ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" ); +fprintf (stderr,"NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" ); +fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]" );fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n" );fprintf (stderr," [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n" );fprintf (stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n" );@@ -185,8 +186,15 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) (r->rtm_family != filter.msrc.family || (filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))return 0 ; -if (filter.rvia.family && r->rtm_family != filter.rvia.family) -return 0 ; +if (filter.rvia.family) { +int family = r->rtm_family; +if (tb[RTA_VIA ]) { +struct rtvia *via =RTA_DATA (tb[RTA_VIA ]); + family = via->rtvia_family; + } +if (family != filter.rvia.family) +return 0 ; + }if (filter.rprefsrc.family && r->rtm_family != filter.rprefsrc.family)return 0 ;@@ -205,6 +213,12 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len) via.family = r->rtm_family;if (tb[RTA_GATEWAY ])memcpy (&via.data,RTA_DATA (tb[RTA_GATEWAY ]), host_len/8 ); +if (tb[RTA_VIA ]) { +size_t len =RTA_PAYLOAD (tb[RTA_VIA ]) -2 ; +struct rtvia *rtvia =RTA_DATA (tb[RTA_VIA ]); + via.family = rtvia->rtvia_family; +memcpy (&via.data, rtvia->rtvia_addr, len); + } }if (filter.rprefsrc.bitlen>0 ) {memset (&prefsrc,0 ,sizeof (prefsrc));@@ -386,6 +400,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)RTA_DATA (tb[RTA_GATEWAY ]), abuf, sizeof(abuf))); } +if (tb[RTA_VIA ]) { +size_t len =RTA_PAYLOAD (tb[RTA_VIA ]) -2 ; +struct rtvia *via =RTA_DATA (tb[RTA_VIA ]); +fprintf (fp,"via %s %s " , +family_name (via->rtvia_family), +format_host (via->rtvia_family, len, via->rtvia_addr, + abuf,sizeof (abuf))); + }if (tb[RTA_OIF ] && filter.oifmask !=-1 )fprintf (fp,"dev %s " ,ll_index_to_name (*(int *)RTA_DATA (tb[RTA_OIF ])));@@ -601,6 +623,14 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)RTA_DATA (tb[RTA_GATEWAY ]), abuf, sizeof(abuf))); } +if (tb[RTA_VIA ]) { +size_t len =RTA_PAYLOAD (tb[RTA_VIA ]) -2 ; +struct rtvia *via =RTA_DATA (tb[RTA_VIA ]); +fprintf (fp,"via %s %s " , +family_name (via->rtvia_family), +format_host (via->rtvia_family, len, via->rtvia_addr, + abuf,sizeof (abuf))); + }if (tb[RTA_FLOW ]) {__u32 to =rta_getattr_u32 (tb[RTA_FLOW ]);__u32 from = to>>16 ;@@ -648,12 +678,23 @@ static int parse_one_nh(struct rtmsg *r, struct rtattr *rta,while (++argv, --argc >0 ) {if (strcmp (*argv,"via" ) ==0 ) {inet_prefix addr; +int family;NEXT_ARG (); -get_addr (&addr, *argv, r->rtm_family); + family =read_family (*argv); +if (family ==AF_UNSPEC ) + family = r->rtm_family; +else +NEXT_ARG (); +get_addr (&addr, *argv, family);if (r->rtm_family ==AF_UNSPEC ) r->rtm_family = addr.family; -rta_addattr_l (rta,4096 ,RTA_GATEWAY , &addr.data, addr.bytelen); - rtnh->rtnh_len +=sizeof (struct rtattr ) + addr.bytelen; +if (addr.family == r->rtm_family) { +rta_addattr_l (rta,4096 ,RTA_GATEWAY , &addr.data, addr.bytelen); + rtnh->rtnh_len +=sizeof (struct rtattr ) + addr.bytelen; + }else { +rta_addattr_l (rta,4096 ,RTA_VIA , &addr.family, addr.bytelen+2 ); + rtnh->rtnh_len +=sizeof (struct rtattr ) + addr.bytelen+2 ; + } }else if (strcmp (*argv,"dev" ) ==0 ) {NEXT_ARG ();if ((rtnh->rtnh_ifindex =ll_name_to_index (*argv)) ==0 ) {@@ -761,12 +802,21 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)addattr_l (&req.n,sizeof (req),RTA_PREFSRC , &addr.data, addr.bytelen); }else if (strcmp (*argv,"via" ) ==0 ) {inet_prefix addr; +int family; gw_ok =1 ;NEXT_ARG (); -get_addr (&addr, *argv, req.r.rtm_family); + family =read_family (*argv); +if (family ==AF_UNSPEC ) + family = req.r.rtm_family; +else +NEXT_ARG (); +get_addr (&addr, *argv, family);if (req.r.rtm_family ==AF_UNSPEC ) req.r.rtm_family = addr.family; -addattr_l (&req.n,sizeof (req),RTA_GATEWAY , &addr.data, addr.bytelen); +if (addr.family == req.r.rtm_family) +addattr_l (&req.n,sizeof (req),RTA_GATEWAY , &addr.data, addr.bytelen); +else +addattr_l (&req.n,sizeof (req),RTA_VIA , &addr.family, addr.bytelen+2 ); }else if (strcmp (*argv,"from" ) ==0 ) {inet_prefix addr;NEXT_ARG ();@@ -1251,8 +1301,14 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)get_unsigned (&mark, *argv,0 ); filter.markmask =-1 ; }else if (strcmp (*argv,"via" ) ==0 ) { +int family;NEXT_ARG (); -get_prefix (&filter.rvia, *argv, do_ipv6); + family =read_family (*argv); +if (family ==AF_UNSPEC ) + family = do_ipv6; +else +NEXT_ARG (); +get_prefix (&filter.rvia, *argv, family); }else if (strcmp (*argv,"src" ) ==0 ) {NEXT_ARG ();get_prefix (&filter.rprefsrc, *argv, do_ipv6);@@ -1554,6 +1610,8 @@ static int iproute_get(int argc, char **argv) tb[RTA_OIF ]->rta_type =0 ;if (tb[RTA_GATEWAY ]) tb[RTA_GATEWAY ]->rta_type =0 ; +if (tb[RTA_VIA ]) + tb[RTA_VIA ]->rta_type =0 ;if (!idev && tb[RTA_IIF ]) tb[RTA_IIF ]->rta_type =0 ; req.n.nlmsg_flags =NLM_F_REQUEST ;man/man8/ip-route.8.in +12
-6@@ -81,13 +81,18 @@ replace " } " .ti -8 .IR NH " := [ " .B via -.IR ADDRESS " ] [ " +[ +.IR FAMILY " ] " ADDRESS " ] [ " .B dev .IR STRING " ] [ " .B weight .IR NUMBER " ] " NHFLAGS .ti -8 +.IR FAMILY " := [ " +.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]" + +.ti -8 .IR OPTIONS " := " FLAGS " [ " .B mtu .IR NUMBER " ] [ "@@ -333,9 +338,10 @@ table by default. the output device name. .TP -.BI via " ADDRESS" -the address of the nexthop router. Actually, the sense of this field -depends on the route type. For normal +.BI via " [ FAMILY ] ADDRESS" +the address of the nexthop router, in the address family FAMILY. +Actually, the sense of this field depends on the route type. For +normal .B unicast routes it is either the true next hop router or, if it is a direct route installed in BSD compatibility mode, it can be a local address@@ -472,7 +478,7 @@ is a complex value with its own syntax similar to the top level argument lists: .in +8 -.BI via " ADDRESS" +.BI via " [ FAMILY ] ADDRESS" - is the nexthop router. .sp@@ -669,7 +675,7 @@ only list routes of this type. only list routes going via this device. .TP -.BI via " PREFIX" +.BI via " [ FAMILY ] PREFIX" only list routes going via the nexthop routers selected by .IR PREFIX "."
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 35 lines · Andy Gospodarek
Quoted 31 lines · roopa
Quoted 19 lines · Eric W. Biederman
Add support for the
RTA_VIAattribute that specifies an address family as well as an address for the next hop gateway.To make it easy to pass this reorder
inet_prefixso that it's tail is a properRTA_VIAattribute.Signed-off-by "Eric W. Biederman" <[email protected]>--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)include/linux/rtnetlink.h +0
-0include/linux/rtnetlink.h enum rtattr_type_t { · line 306
Quoted 4 lines
include/linux/rtnetlink.h +1
-0@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , + RTA_VIA,eric, if its not too late, what do you think about renaming
RTA_VIAattribute toRTA_NEWGATEWAY(similar to your newRTA_NEWDSTattribute to specify a label dst) ?.RTA_VIAis fine too.
This is indeed a new way to specify a gateway (and can/will be used by RFC 5549 in the future).Quoted 3 lines
If there is interest in renaming it to
RTA_NEWGATEWAY(or any other name, cant think of anything better right now),
I will be happy to submit a follow-on patch.
Quoted 6 lines
FWIW, I actually do not mind the name
RTA_VIA. I was planning to replace use ofRTA_GATEWAYin iproute2 and just usaRTA_VIAfor all nexthops regardless of the address family of the dest route or nexthop and would allow easy creation of the infrastructure needed to support RFC5549 -- obviously while keeping backwards compatibility in the kernel.
ok, good to know.
Quoted 5 lines
This was what my orignal set did (not submitted to netdev, but discussed with others at netconf) and it was much cleaner code-wise (but not ideal as I overloaded the use of
RTA_GATEWAYand that was not pleasing to me or others).
ok, yeah i remember you had RTA_GATEWAY6 or something like that.
just to clarify, i was not suggesting overloading.
eric introduced cleaner abstracted attributes for RTA_DST and RTA_GATEWAY.
One is called RTA_NEWDST and I was thinking if changing RTA_GATEWAY to RTA_NEWGATEWAY would be less confusing (because, the rest of the structures (ipv4/ipv6) where you will put the RTA_VIA information is still called gw).
No worries, RTA_VIA can stay if more people prefer that.
Thanks!.
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 36 lines · roopa
Quoted 35 lines · Andy Gospodarek
Quoted 34 lines · roopa
Quoted 19 lines · Eric W. Biederman
Add support for the
RTA_VIAattribute that specifies an address family as well as an address for the next hop gateway.To make it easy to pass this reorder
inet_prefixso that it's tail is a properRTA_VIAattribute.Signed-off-by "Eric W. Biederman" <[email protected]>--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)include/linux/rtnetlink.h +0
-0include/linux/rtnetlink.h enum rtattr_type_t { · line 306
Quoted 4 lines
include/linux/rtnetlink.h +1
-0@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , + RTA_VIA,eric, if its not too late, what do you think about renaming
RTA_VIAattribute toRTA_NEWGATEWAY(similar to your newRTA_NEWDSTattribute to specify a label dst) ?.RTA_VIAis fine too.
This is indeed a new way to specify a gateway (and can/will be used by RFC 5549 in the future).If there is interest in renaming it to
RTA_NEWGATEWAY(or any other name, cant think of anything better right now),
I will be happy to submit a follow-on patch.
Quoted 7 lines
Quoted 6 lines
FWIW, I actually do not mind the name
RTA_VIA. I was planning to replace use ofRTA_GATEWAYin iproute2 and just usaRTA_VIAfor all nexthops regardless of the address family of the dest route or nexthop and would allow easy creation of the infrastructure needed to support RFC5549 -- obviously while keeping backwards compatibility in the kernel.ok, good to know.
To answer the original question. The new in RTA_NEWDST is not new as in a new attribute it is new as in replace the destination address with a new destination address. NAT in other words. Which is how mpls routing works. Each hop NATs the address before sending the packet on.
Quoted 14 lines
Quoted 4 lines
This was what my orignal set did (not submitted to netdev, but discussed with others at netconf) and it was much cleaner code-wise (but not ideal as I overloaded the use of
RTA_GATEWAYand that was not pleasing to me or others).ok, yeah i remember you had
RTA_GATEWAY6or something like that.just to clarify, i was not suggesting overloading.
eric introduced cleaner abstracted attributes forRTA_DSTandRTA_GATEWAY. One is calledRTA_NEWDSTand I was thinking if changingRTA_GATEWAYtoRTA_NEWGATEWAY
would be less confusing (because, the rest of the structures (ipv4/ipv6) where you will put theRTA_VIAinformation is still called gw).
Quoted 1 line
No worries,
RTA_VIAcan stay if more people prefer that.
As long as the number and the semantics don't change I don't much care.
However I think via is probably what we should have called the concept and the field in the first place, and certainly there are corner cases where the machine where we are going via is not actually a gateway but the final destination, when you are talking about multiple protocols.
Regardless the name RTA_VIA is my best attempt in that direction.
All of my added support in iproute2 should work for RFC5549. As well as for mpls.
Eric
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 44 lines · Eric W. Biederman
Quoted 42 lines · roopa
Quoted 41 lines · Andy Gospodarek
Quoted 31 lines · roopa
Quoted 19 lines · Eric W. Biederman
Add support for the
RTA_VIAattribute that specifies an address family as well as an address for the next hop gateway.To make it easy to pass this reorder
inet_prefixso that it's tail is a properRTA_VIAattribute.Signed-off-by "Eric W. Biederman" <[email protected]>--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)include/linux/rtnetlink.h +0
-0include/linux/rtnetlink.h enum rtattr_type_t { · line 306
Quoted 4 lines
include/linux/rtnetlink.h +1
-0@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , + RTA_VIA,eric, if its not too late, what do you think about renaming
RTA_VIAattribute toRTA_NEWGATEWAY(similar to your newRTA_NEWDSTattribute to specify a label dst) ?.RTA_VIAis fine too.
This is indeed a new way to specify a gateway (and can/will be used by RFC 5549 in the future).Quoted 3 lines
If there is interest in renaming it to
RTA_NEWGATEWAY(or any other name, cant think of anything better right now),
I will be happy to submit a follow-on patch.FWIW, I actually do not mind the name
RTA_VIA. I was planning to replace use ofRTA_GATEWAYin iproute2 and just usaRTA_VIAfor all nexthops regardless of the address family of the dest route or nexthop and would allow easy creation of the infrastructure needed to support RFC5549 -- obviously while keeping backwards compatibility in the kernel.
Quoted 7 lines
Quoted 1 line
ok, good to know.
To answer the original question. The new in
RTA_NEWDSTis not new as in a new attribute it is new as in replace the destination address with a new destination address. NAT in other words. Which is how mpls routing works. Each hop NATs the address before sending the packet on.
At the edge, when doing IPoMPLS, we'll be imposing a set of labels on top of the packet rather than replacing, but the same semantics can be applied because the destination address is now different and becomes a label stack.
One thing to note is that the destination address replaced/imposed could change based on the path selected, when there is ECMP. So, I propose that the iproute2 syntax of "as [to]" be reconsidered for MPLS, otherwise we'll end up with something like the following when this is extended to setup IPoMPLS direct forwarding with ECMP:
ip route add 147.1.1.0/24 nexthop as to 400/2230 via inet 192.168.1.1 dev eth0 nexthop as to 600/2400 via inet 192.168.2.1 dev eth1
Instead, if we use the specifier "label", we'll get:
ip route add 147.1.1.0/24 nexthop via inet 192.168.1.1 dev eth0 label 400/2230 nexthop via inet 192.168.2.1 dev eth1 label 600/2400
The transit case (label swapping) would look like:
ip -f mpls route add 400 via inet 192.168.1.10 dev eth0 label 500
The syntax can then be better extended to specify a label operation such as "pop" which would be needed when performing ultimate hop pop (UHP) and then lookup/forward based on underlying label stack or IP header.
A new application besides MPLS that needs to modify the destination address would use its own keyword but encode using the RTA_NEWDST attribute.
Quoted 29 lines
Quoted 14 lines
Quoted 4 lines
This was what my orignal set did (not submitted to netdev, but discussed with others at netconf) and it was much cleaner code-wise (but not ideal as I overloaded the use of
RTA_GATEWAYand that was not pleasing to me or others).ok, yeah i remember you had
RTA_GATEWAY6or something like that.just to clarify, i was not suggesting overloading.
eric introduced cleaner abstracted attributes forRTA_DSTandRTA_GATEWAY. One is calledRTA_NEWDSTand I was thinking if changingRTA_GATEWAYtoRTA_NEWGATEWAY
would be less confusing (because, the rest of the structures (ipv4/ipv6) where you will put theRTA_VIAinformation is still called gw).Quoted 1 line
No worries,
RTA_VIAcan stay if more people prefer that.As long as the number and the semantics don't change I don't much care.
However I think via is probably what we should have called the concept and the field in the first place, and certainly there are corner cases where the machine where we are going via is not actually a gateway but the final destination, when you are talking about multiple protocols.
Regardless the name
RTA_VIAis my best attempt in that direction.All of my added support in iproute2 should work for RFC5549. As well as for mpls.
Eric
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 4 lines · Vivek Venkatraman
At the edge, when doing IPoMPLS, we'll be imposing a set of labels on top of the packet rather than replacing, but the same semantics can be applied because the destination address is now different and becomes a label stack.
Exactly how this will happen is an open question. The hard part is we need something light weight enough that we can scale to 1 million routes, aka a full routing table.
Network devices consume much too much memory to contemplate having a different network device for each of 1 million different routes.
The transform infrastructure (xfrm) that is used for ipsec looks attractive for imposing tunnels but it is clumsy, and does not map well to the kinds of tunnels IPoMPLS traffic needs.
Having something in the ipv4 and ipv6 fib entry say a pointer or a 32bit key that refers to a struct mpls_route to impose looks like what we want int he abstract. What the userspace interface for that implemenation is something that I do not see clearly. Ideally we build a userspace interface that works not only for MPLS but also for other tunnel types
like IPIP, GRE, etc. This would allow not only MPLS tunnels but other
tunnel types to be supported up to the full routing table size.
Perhaps a new attribute RTA_ENCAP that encodes a structure with a tunnel type and enough information to encode the tunnel header. I would have to make a survey of the existing tunnel types to see if there is enough of a pattern an option that works for multiple protocols could actually be achieved.
Using a tunnel that is not a network device and as such does not need to keep packet counters looks like it will scale much better than our other options, even with the best memory usage simplications I can imagine for network devices. Maintenance of per cpu counters (which are necessary for performance) requires a non-trivial amount of memory and as such are much harder to scale.
Quoted 8 lines
One thing to note is that the destination address replaced/imposed could change based on the path selected, when there is ECMP. So, I propose that the iproute2 syntax of "as [to]" be reconsidered for MPLS, otherwise we'll end up with something like the following when this is extended to setup IPoMPLS direct forwarding with ECMP:
ip route add 147.1.1.0/24 nexthop as to 400/2230 via inet 192.168.1.1 dev eth0 nexthop as to 600/2400 via inet 192.168.2.1 dev eth1
That does not work with the semantics of the RTA_NEWDST message require the new address to be in the same address family as the old address. So it is useful for NATing IPv4 or IPv6 with routes (if you are so inclined) but it is not useful for imposing an mpls header.
Quoted 5 lines
Instead, if we use the specifier "label", we'll get:
ip route add 147.1.1.0/24 nexthop via inet 192.168.1.1 dev eth0 label 400/2230 nexthop via inet 192.168.2.1 dev eth1 label 600/2400
Quoted 8 lines
The transit case (label swapping) would look like:
ip -f mpls route add 400 via inet 192.168.1.10 dev eth0 label 500
The syntax can then be better extended to specify a label operation such as "pop" which would be needed when performing ultimate hop pop (UHP) and then lookup/forward based on underlying label stack or IP header.
Pop is the case where where the RTA_NEWDST attribute is empty (or unspecified).
Quoted 1 line
From an mpls perspective the
RTA_DSTlabel is always popped (if it
matches) and the RTA_NEWDST label stack is always pushed.
Quoted 3 lines
A new application besides MPLS that needs to modify the destination address would use its own keyword but encode using the
RTA_NEWDSTattribute.
Eric
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
Quoted 7 lines · Eric W. Biederman
Quoted 4 lines · Vivek Venkatraman
At the edge, when doing IPoMPLS, we'll be imposing a set of labels on top of the packet rather than replacing, but the same semantics can be applied because the destination address is now different and becomes a label stack.
Quoted 7 lines
Exactly how this will happen is an open question. The hard part is we need something light weight enough that we can scale to 1 million routes, aka a full routing table.
Network devices consume much too much memory to contemplate having a different network device for each of 1 million different routes.
Agree and this is the exact point I had raised about your initial proposal to inject IP into an MPLS tunnel.
Quoted 18 lines
The transform infrastructure (xfrm) that is used for ipsec looks attractive for imposing tunnels but it is clumsy, and does not map well to the kinds of tunnels IPoMPLS traffic needs.
Having something in the ipv4 and ipv6 fib entry say a pointer or a 32bit key that refers to a struct
mpls_routeto impose looks like what we want int he abstract. What the userspace interface for that implemenation is something that I do not see clearly. Ideally we build a userspace interface that works not only for MPLS but also for other tunnel types
like IPIP, GRE, etc. This would allow not only MPLS tunnels but other
tunnel types to be supported up to the full routing table size.Perhaps a new attribute
RTA_ENCAPthat encodes a structure with a tunnel type and enough information to encode the tunnel header. I would have to make a survey of the existing tunnel types to see if there is enough of a pattern an option that works for multiple protocols could actually be achieved.
Quoted 7 lines
Using a tunnel that is not a network device and as such does not need to keep packet counters looks like it will scale much better than our other options, even with the best memory usage simplications I can imagine for network devices. Maintenance of per cpu counters (which are necessary for performance) requires a non-trivial amount of memory and as such are much harder to scale.
Yes. I believe there are 2 use cases to consider:
a) When MPLS LSPs specify a labeled-path and are not a tunnel per se. This would be the case when they are setup hop-by-hop to following routing, as would be the case using a protocol such as LDP or BGP. In this case, the label stack is really just an encap and there is no separate network device associated with each LSP (and certainly not with any application/inner label such as a VPN label or a PWE label).
I believe this will be the common use-case in the data center and in certain situations in provider networks.
b) When MPLS LSPs actually represent a tunnel interface. This would be the case when they are traffic-engineered using a protocol such as RSVP-TE. A network device would be associated with this tunnel and specify the tunnel encapsulation (one or more labels) but the labels imposed by the application would still come from the corresponding IP or L2 constructs (e.g., fib entry).
This use-case is likely to be seen more in provider networks than in the data center.
We have been looking into (a) and it is along the lines you mention above (fib entry refers to mpls_route), but not flushed out enough to post and seek opinion. In terms of the user interface (iproute2 commands), it is along the lines of my examples, though I have clearly overlooked the point you make below about RTA_NEWDST.
Quoted 6 lines
Quoted 6 lines
One thing to note is that the destination address replaced/imposed could change based on the path selected, when there is ECMP. So, I propose that the iproute2 syntax of "as [to]" be reconsidered for MPLS, otherwise we'll end up with something like the following when this is extended to setup IPoMPLS direct forwarding with ECMP:
Quoted 8 lines
Quoted 2 lines
ip route add 147.1.1.0/24 nexthop as to 400/2230 via inet 192.168.1.1 dev eth0 nexthop as to 600/2400 via inet 192.168.2.1 dev eth1
That does not work with the semantics of the
RTA_NEWDSTmessage require the new address to be in the same address family as the old address. So it is useful for NATing IPv4 or IPv6 with routes (if you are so inclined) but it is not useful for imposing an mpls header.
I had overlooked this. I think now that it would be handy to allow the address family to be specified for the new address so it can be used in both cases (edge and transit). A keyword like "label" could automatically imply AF_MPLS for the new address and a new application could follow suit.
Quoted 14 lines
Quoted 5 lines
Instead, if we use the specifier "label", we'll get:
ip route add 147.1.1.0/24 nexthop via inet 192.168.1.1 dev eth0 label 400/2230 nexthop via inet 192.168.2.1 dev eth1 label 600/2400
Quoted 8 lines
The transit case (label swapping) would look like:
ip -f mpls route add 400 via inet 192.168.1.10 dev eth0 label 500
The syntax can then be better extended to specify a label operation such as "pop" which would be needed when performing ultimate hop pop (UHP) and then lookup/forward based on underlying label stack or IP header.
Quoted 6 lines
Pop is the case where where the
RTA_NEWDSTattribute is empty (or unspecified).From an mpls perspective the
RTA_DSTlabel is always popped (if it matches) and theRTA_NEWDSTlabel stack is always pushed.
The idea was to pop and do a subsequent lookup rather than pop and forward. This would be an alternative to forwarding to loopback device in order to lookup on inner labels.
Quoted 5 lines
Quoted 3 lines
A new application besides MPLS that needs to modify the destination address would use its own keyword but encode using the
RTA_NEWDSTattribute.Eric
Re: [PATCH net-next 6/8] iproute2: Add support for the RTA_VIA attribute
In reply to Eric W. BiedermanQuoted 44 lines · Eric W. Biederman
Quoted 42 lines · roopa
Quoted 41 lines · Andy Gospodarek
Quoted 31 lines · roopa
Quoted 19 lines · Eric W. Biederman
Add support for the
RTA_VIAattribute that specifies an address family as well as an address for the next hop gateway.To make it easy to pass this reorder
inet_prefixso that it's tail is a properRTA_VIAattribute.Signed-off-by "Eric W. Biederman" <[email protected]>--- include/linux/rtnetlink.h | 7 +++++ include/utils.h | 7 +++-- ip/iproute.c | 76 +++++++++++++++++++++++++++++++++++++++++------ man/man8/ip-route.8.in | 18 +++++++---- 4 files changed, 90 insertions(+), 18 deletions(-)include/linux/rtnetlink.h +0
-0include/linux/rtnetlink.h enum rtattr_type_t { · line 306
Quoted 4 lines
include/linux/rtnetlink.h +1
-0@@ -303,6 +303,7 @@ enum rtattr_type_t {RTA_TABLE ,RTA_MARK ,RTA_MFC_STATS , + RTA_VIA,eric, if its not too late, what do you think about renaming
RTA_VIAattribute toRTA_NEWGATEWAY(similar to your newRTA_NEWDSTattribute to specify a label dst) ?.RTA_VIAis fine too.
This is indeed a new way to specify a gateway (and can/will be used by RFC 5549 in the future).Quoted 3 lines
If there is interest in renaming it to
RTA_NEWGATEWAY(or any other name, cant think of anything better right now),
I will be happy to submit a follow-on patch.FWIW, I actually do not mind the name
RTA_VIA. I was planning to replace use ofRTA_GATEWAYin iproute2 and just usaRTA_VIAfor all nexthops regardless of the address family of the dest route or nexthop and would allow easy creation of the infrastructure needed to support RFC5549 -- obviously while keeping backwards compatibility in the kernel.
Quoted 5 lines
Quoted 1 line
ok, good to know.
To answer the original question. The new in
RTA_NEWDSTis not new as in a new attribute it is new as in replace the destination address with a new destination address. NAT in other words. Which is how mpls routing works. Each hop NATs the address before sending the packet on.
thanks for the clarifying this.
Quoted 15 lines
Quoted 15 lines
Quoted 5 lines
This was what my orignal set did (not submitted to netdev, but discussed with others at netconf) and it was much cleaner code-wise (but not ideal as I overloaded the use of
RTA_GATEWAYand that was not pleasing to me or others).ok, yeah i remember you had
RTA_GATEWAY6or something like that.just to clarify, i was not suggesting overloading.
eric introduced cleaner abstracted attributes forRTA_DSTandRTA_GATEWAY. One is calledRTA_NEWDSTand I was thinking if changingRTA_GATEWAYtoRTA_NEWGATEWAY
would be less confusing (because, the rest of the structures (ipv4/ipv6) where you will put theRTA_VIAinformation is still called gw).
Quoted 7 lines
Quoted 1 line
No worries,
RTA_VIAcan stay if more people prefer that.As long as the number and the semantics don't change I don't much care.
However I think via is probably what we should have called the concept and the field in the first place, and certainly there are corner cases where the machine where we are going via is not actually a gateway but the final destination, when you are talking about multiple protocols.
agreed.
Quoted 2 lines
Regardless the name
RTA_VIAis my best attempt in that direction.
ack
Quoted 5 lines
All of my added support in iproute2 should work for RFC5549. As well as for mpls.
agreed.
and thanks.
PATCH 7/8 iproute2: Add support for the RTA_NEWDST attribute.
In reply to Eric W. BiedermanThis attribute is like RTA_DST except it specifies the destination address to place on a packet when it leaves the host. For ip based protocols this is destination NAT and not a common part of forwarding. For protocols like MPLS label swapping is something that typically happens on every hop.
There is likely to be a RTA_NEWSRC at some point so RTA_NEWDST is printed as "as to" and can be specified either as "as to" or just "as"
--- include/linux/rtnetlink.h | 1 + ip/iproute.c | 19 ++++++++++++++++++- man/man8/ip-route.8.in | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-)
include/linux/rtnetlink.h +1 -0
@@ -304,6 +304,7 @@ enum rtattr_type_t {RTA_MARK ,RTA_MFC_STATS ,RTA_VIA , +RTA_NEWDST , __RTA_MAX };
ip/iproute.c +18 -1
@@ -77,7 +77,7 @@ static void usage(void)fprintf (stderr,"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" );fprintf (stderr,"NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" );fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]" ); -fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ]\n" ); +fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n" );fprintf (stderr," [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n" );fprintf (stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n" );fprintf (stderr," [ ssthresh NUMBER ] [ realms REALM ] [ src ADDRESS ]\n" );
@@ -388,6 +388,13 @@ int print_route(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) }else if (r->rtm_src_len) {fprintf (fp,"from 0/%u " , r->rtm_src_len); } +if (tb[RTA_NEWDST ]) { +fprintf (fp,"as to %s " ,format_host (r->rtm_family, +RTA_PAYLOAD (tb[RTA_NEWDST ]), +RTA_DATA (tb[RTA_NEWDST ]), + abuf,sizeof (abuf)) + ); + }if (r->rtm_tos && filter.tosmask !=-1 ) {SPRINT_BUF (b1);fprintf (fp,"tos %s " ,rtnl_dsfield_n2a (r->rtm_tos, b1,sizeof (b1)));
@@ -800,6 +807,16 @@ static int iproute_modify(int cmd, unsigned flags, int argc, char **argv)if (req.r.rtm_family ==AF_UNSPEC ) req.r.rtm_family = addr.family;addattr_l (&req.n,sizeof (req),RTA_PREFSRC , &addr.data, addr.bytelen); + }else if (strcmp (*argv,"as" ) ==0 ) { +inet_prefix addr; +NEXT_ARG (); +if (strcmp (*argv,"to" ) ==0 ) { +NEXT_ARG (); + } +get_addr (&addr, *argv, req.r.rtm_family); +if (req.r.rtm_family ==AF_UNSPEC ) + req.r.rtm_family = addr.family; +addattr_l (&req.n,sizeof (req),RTA_NEWDST , &addr.data, addr.bytelen); }else if (strcmp (*argv,"via" ) ==0 ) {inet_prefix addr;int family;
man/man8/ip-route.8.in +5 -0
@@ -98,6 +98,11 @@ replace " } " .IR NUMBER " ] [ " .B advmss .IR NUMBER " ] [ " +.B as +[ +.B to +] +.IR ADDRESS " ]" .B rtt .IR TIME " ] [ " .B rttvar
Signature · 1 line
2.2.1
PATCH 8/8 iproute2: Add basic mpls support to iproute
In reply to Eric W. Biederman- Pull in the uapi mpls.h
- Update rtnetlink.h to include the mpls rtnetlink notification multicast group.
- Define AF_MPLS in utils.h if it is not defined from elsewhere
as is done with AF_DECnet
The address syntax for multiple mpls labels is a complete invention. When I looked there seemed to be no wide spread convention for talking about an mpls label stack in text for. Sometimes people did:
"{ Label1, Label2, Label3 }", sometimes people would do:
"[ label3, label2, label1 ]", and most of the time label stacks were not explicitly shown at all.
The syntax I wound up using, so it would not have spaces and so it would visually distinct from other kinds of addresses is.
label1/label2/label3 Where label1 is the label at the top of the label stack and label3 is the label at the bottom on the label stack.
When there is a single label this matches what seems to be convention with other tools. Just print out the numeric value of the mpls label.
The netlink protocol for labels uses the on the wire format for a label stack. The ttl and traffic class are expected to be 0. Using the on the wire format is common and what happens with other address types. BGP when passing label stacks also uses this technique with the exception that the ttl byte is not included making each label in a BGP label stack 3 bytes instead of 4.
--- Makefile | 3 +++ include/linux/mpls.h | 34 +++++++++++++++++++++++++++ include/linux/rtnetlink.h | 2 ++ include/utils.h | 10 ++++++++ ip/ip.c | 4 +++- ip/ipmonitor.c | 3 +++ ip/iproute.c | 2 +- lib/mpls_ntop.c | 48 +++++++++++++++++++++++++++++++++++++++ lib/mpls_pton.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++ lib/utils.c | 30 ++++++++++++++++++++++-- man/man8/ip-route.8.in | 2 +- man/man8/ip.8 | 7 +++++- 12 files changed, 197 insertions(+), 6 deletions(-) create mode 100644 include/linux/mpls.h create mode 100644 lib/mpls_ntop.c create mode 100644 lib/mpls_pton.c
Makefile +3 -0
@@ -26,6 +26,9 @@ ADDLIB+=dnet_ntop.o dnet_pton.o #options for ipx ADDLIB+=ipx_ntop.o ipx_pton.o +#options for mpls +ADDLIB+=mpls_ntop.o mpls_pton.o + CC = gcc HOSTCC = gcc DEFINES += -D_GNU_SOURCE
include/linux/mpls.h new file +34 -0
@@ -0,0 +1,34 @@ +#ifndef _UAPI_MPLS_H +#define _UAPI_MPLS_H + +#include <linux/types.h> +#include <asm/byteorder.h> + +/* Reference: RFC 5462, RFC 3032 +* +* 0 1 2 3 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* | Label | TC |S| TTL | +* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +* +* Label: Label Value, 20 bits +* TC: Traffic Class field, 3 bits +* S: Bottom of Stack, 1 bit +* TTL: Time to Live, 8 bits +*/ + +struct mpls_label { +__be32 entry; +}; + +#define MPLS_LS_LABEL_MASK 0xFFFFF000 +#define MPLS_LS_LABEL_SHIFT 12 +#define MPLS_LS_TC_MASK 0x00000E00 +#define MPLS_LS_TC_SHIFT 9 +#define MPLS_LS_S_MASK 0x00000100 +#define MPLS_LS_S_SHIFT 8 +#define MPLS_LS_TTL_MASK 0x000000FF +#define MPLS_LS_TTL_SHIFT 0 + +#endif /* _UAPI_MPLS_H */
include/linux/rtnetlink.h +2 -0
@@ -629,6 +629,8 @@ enum rtnetlink_groups {#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF RTNLGRP_MDB,#define RTNLGRP_MDB RTNLGRP_MDB + RTNLGRP_MPLS_ROUTE, +#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE __RTNLGRP_MAX };#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
include/utils.h +10 -0
@@ -78,6 +78,13 @@ struct ipx_addr {u_int8_t ipx_node[IPX_NODE_LEN ]; }; +#ifndef AF_MPLS +# define AF_MPLS 28 +#endif + +/* Maximum number of labels the mpls helpers support */ +#define MPLS_MAX_LABELS 8 +extern __u32 get_addr32 (const char *name);extern int get_addr_1 (inet_prefix *dst,const char *arg,int family);extern int get_prefix_1 (inet_prefix *dst,char *arg,int family);
@@ -126,6 +133,9 @@ int dnet_pton(int af, const char *src, void *addr);const char *ipx_ntop (int af,const void *addr,char *str,size_t len);int ipx_pton (int af,const char *src,void *addr); +const char *mpls_ntop (int af,const void *addr,char *str,size_t len); +int mpls_pton (int af,const char *src,void *addr); +extern int __iproute2_hz_internal;extern int __get_hz (void );
ip/ip.c +3 -1
@@ -52,7 +52,7 @@ static void usage(void)" netns | l2tp | fou | tcp_metrics | token | netconf }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -h[uman-readable] | -iec |\n" -" -f[amily] { inet | inet6 | ipx | dnet | bridge | link } |\n" +" -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n" " -4 | -6 | -I | -D | -B | -0 |\n" " -l[oops] { maximum-addr-flush-attempts } |\n" " -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
@@ -206,6 +206,8 @@ int main(int argc, char **argv) preferred_family =AF_IPX ; }else if (strcmp (opt,"-D" ) ==0 ) { preferred_family = AF_DECnet; + }else if (strcmp (opt,"-M" ) ==0 ) { + preferred_family =AF_MPLS ; }else if (strcmp (opt,"-B" ) ==0 ) { preferred_family =AF_BRIDGE ; } else if (matches(opt, "-human") == 0 ||
ip/ipmonitor.c +3 -0
@@ -158,6 +158,7 @@ int do_ipmonitor(int argc, char **argv) groups |=nl_mgrp (RTNLGRP_IPV6_IFADDR ); groups |=nl_mgrp (RTNLGRP_IPV4_ROUTE ); groups |=nl_mgrp (RTNLGRP_IPV6_ROUTE ); + groups |=nl_mgrp (RTNLGRP_MPLS_ROUTE ); groups |=nl_mgrp (RTNLGRP_IPV4_MROUTE ); groups |=nl_mgrp (RTNLGRP_IPV6_MROUTE ); groups |=nl_mgrp (RTNLGRP_IPV6_PREFIX );
@@ -235,6 +236,8 @@ int do_ipmonitor(int argc, char **argv) groups |=nl_mgrp (RTNLGRP_IPV4_ROUTE );if (!preferred_family || preferred_family ==AF_INET6 ) groups |=nl_mgrp (RTNLGRP_IPV6_ROUTE ); +if (!preferred_family || preferred_family ==AF_MPLS ) + groups |=nl_mgrp (RTNLGRP_MPLS_ROUTE ); }if (lmroute) {if (!preferred_family || preferred_family ==AF_INET )
ip/iproute.c +1 -1
@@ -76,7 +76,7 @@ static void usage(void)fprintf (stderr," [ scope SCOPE ] [ metric METRIC ]\n" );fprintf (stderr,"INFO_SPEC := NH OPTIONS FLAGS [ nexthop NH ]...\n" );fprintf (stderr,"NH := [ via [ FAMILY ] ADDRESS ] [ dev STRING ] [ weight NUMBER ] NHFLAGS\n" ); -fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | bridge | link ]" ); +fprintf (stderr,"FAMILY := [ inet | inet6 | ipx | dnet | mpls | bridge | link ]" );fprintf (stderr,"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n" );fprintf (stderr," [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n" );fprintf (stderr," [ window NUMBER] [ cwnd NUMBER ] [ initcwnd NUMBER ]\n" );
lib/mpls_ntop.c new file +48 -0
48 lines not on this page · raw message
lib/mpls_pton.c new file +58 -0
58 lines not on this page · raw message
lib/utils.c +28 -2
@@ -26,6 +26,7 @@#include <linux/pkt_sched.h> #include <linux/param.h> #include <linux/if_arp.h> +#include <linux/mpls.h> #include <time.h> #include <sys/time.h> #include <errno.h>
@@ -390,7 +391,7 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)if (strcmp (name,"default" ) ==0 ||strcmp (name,"all" ) ==0 ||strcmp (name,"any" ) ==0 ) { -if (family == AF_DECnet) +if ((family == AF_DECnet) || (family ==AF_MPLS ))return -1 ; addr->family = family; addr->bytelen = (family ==AF_INET6 ?16 :4 );
@@ -432,6 +433,23 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)return 0 ; } +if (family ==AF_MPLS ) { +int i; + addr->family =AF_MPLS ; +if (mpls_pton (AF_MPLS , name, addr->data) <=0 ) +return -1 ; + addr->bytelen =4 ; + addr->bitlen =20 ; +/* How many bytes do I need? */ +for (i =0 ; i <8 ; i++) { +if (ntohl (addr->data[i]) &MPLS_LS_S_MASK ) { + addr->bytelen = (i +1 )*4 ; +break ; + } + } +return 0 ; + } + addr->family =AF_INET ;if (family !=AF_UNSPEC && family !=AF_INET )return -1 ;
@@ -455,6 +473,8 @@ int af_bit_len(int af)return 16 ;case AF_IPX :return 80 ; +case AF_MPLS : +return 20 ; }return 0 ;
@@ -476,7 +496,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)if (strcmp (arg,"default" ) ==0 ||strcmp (arg,"any" ) ==0 ||strcmp (arg,"all" ) ==0 ) { -if (family == AF_DECnet) +if ((family == AF_DECnet) || (family =AF_MPLS ))return -1 ; dst->family = family; dst->bytelen =0 ;
@@ -651,6 +671,8 @@ const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflencase AF_INET :case AF_INET6 :return inet_ntop (af, addr, buf, buflen); +case AF_MPLS : +return mpls_ntop (af, addr, buf, buflen);case AF_IPX :return ipx_ntop (af, addr, buf, buflen);case AF_DECnet:
@@ -679,6 +701,8 @@ int read_family(const char *name) family =AF_PACKET ; else if (strcmp(name, "ipx") == 0) family =AF_IPX ; + else if (strcmp(name, "mpls") == 0) + family =AF_MPLS ; else if (strcmp(name, "bridge") == 0) family =AF_BRIDGE ;return family;
@@ -696,6 +720,8 @@ const char *family_name(int family)return "link" ;if (family ==AF_IPX )return "ipx" ; +if (family ==AF_MPLS ) +return "mpls" ;if (family ==AF_BRIDGE )return "bridge" ;return "???" ;
man/man8/ip-route.8.in +1 -1
@@ -90,7 +90,7 @@ replace " } " .ti -8 .IR FAMILY " := [ " -.BR inet " | " inet6 " | " ipx " | " dnet " | " bridge " | " link " ]" +.BR inet " | " inet6 " | " ipx " | " dnet " | " mpls " | " bridge " | " link " ]" .ti -8 .IR OPTIONS " := " FLAGS " [ "
man/man8/ip.8 +6 -1
@@ -73,7 +73,7 @@ Zero (0) means loop until all addresses are removed. .TP .BR "\-f" , " \-family " <FAMILY> Specifies the protocol family to use. The protocol family identifier can be one of -.BR "inet" , " inet6" , " bridge" , " ipx" , " dnet" +.BR "inet" , " inet6" , " bridge" , " ipx" , " dnet" , " mpls" or .BR link . If this option is not present,
@@ -115,6 +115,11 @@ shortcut for .BR "\-family ipx" . .TP +.B \-M +shortcut for +.BR "\-family mpls" . + +.TP .B \-0 shortcut for .BR "\-family link" .
Signature · 1 line
2.2.1
Stephen Hemminger
AppliedQuoted 18 lines · On Fri, 13 Mar 2015 13:50:11 -0500 [email protected] (Eric W. Biederman)…
This set of changes adds support for nexthops in different address families, with the new netlink
RTA_VIAoption.Support is added for routes that change the destination address (as MPLS does) with the
RTA_NEWDSTattribute.Support for MPLS addresses is added (for multiple labels I had to make up the syntax I used label/label/label as it fits in well with addresses that don't have a space in them).
Support for these options is merged into David's net-next kernel tree, and the meaning of the options is unlikely to change in any significant way before this code merges upstream.
The documentation has been updated to report that the new options are present and to report roughly what they do. This includes ip --help and the man pages.
Quoted 9 lines
Eric W. Biederman (8):
iproute2: Add a source addres length parameter tort_addr_n2a
iproute2: Make the addr argument ofll_addr_n2aconst
iproute2: Add support for printingAF_PACKETaddresses
iproute2: Add address family to/from string helper functions.
iproute2: misc whitespace cleanup
iproute2: Add support forRTA_VIAattributes
iproute2: Add support for theRTA_NEWDSTattribute.
iproute2: Add basic mpls support to iproute
Applied to net-next branch of iproute.
Only change was to use result of kernel make headers_install version of mpls.h