ip: add support for more MPLS labels
Subsystems (3)
PATCH 1/1 ip: add support for more MPLS labels
Kernel now supports up to 30 labels but not defined as part of the uapi. iproute2 handles up to 8 labels but in a non-consistent way. Update ip to handle more labels, but in a more programmatic way.
For the MPLS address family, the data field in inet_prefix is used for labels. Increase that field to 64 u32's -- 64 as nothing more than a convenient power of 2 number.
Update mpls_pton to take the length of the address field, convert that length to number of labels and add better error handling to the parsing of the user supplied string.
--- include/utils.h | 7 ++----- lib/mpls_pton.c | 11 +++++++---- lib/utils.c | 7 +++++-- 3 files changed, 14 insertions(+), 11 deletions(-)
include/utils.h +2 -5
@@ -61,7 +61,7 @@ typedef struct__s16 bitlen;/* These next two fields match rtvia */ __u16 family; -__u32 data[8 ]; +__u32 data[64 ]; } inet_prefix;#define PREFIXLEN_SPECIFIED 1
@@ -88,9 +88,6 @@ struct ipx_addr {# define AF_MPLS 28#endif -/* Maximum number of labels the mpls helpers support */ -#define MPLS_MAX_LABELS 8 -__u32 get_addr32 (const char *name);int get_addr_1 (inet_prefix *dst,const char *arg,int family);int get_prefix_1 (inet_prefix *dst,char *arg,int family);
@@ -155,7 +152,7 @@ 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); +int mpls_pton (int af,const char *src,void *addr,size_t alen);extern int __iproute2_hz_internal;int __get_hz (void );
lib/mpls_pton.c +7 -4
@@ -7,12 +7,13 @@#include "utils.h" -static int mpls_pton1 (const char *name,struct mpls_label *addr) +static int mpls_pton1 (const char *name,struct mpls_label *addr, +unsigned int maxlabels) {char *endp;unsigned count; -for (count =0 ; count <MPLS_MAX_LABELS ; count++) { +for (count =0 ; count < maxlabels; count++) {unsigned long label; label =strtoul (name, &endp,0 );
@@ -37,17 +38,19 @@ static int mpls_pton1(const char *name, struct mpls_label *addr) addr +=1 ; }/* The address was too long */ +fprintf (stderr,"Error: too many labels.\n" );return 0 ; } -int mpls_pton (int af,const char *src,void *addr) +int mpls_pton (int af,const char *src,void *addr,size_t alen) { +unsigned int maxlabels = alen /sizeof (struct mpls_label );int err;switch (af) {case AF_MPLS : errno =0 ; - err =mpls_pton1 (src, (struct mpls_label *)addr); + err =mpls_pton1 (src, (struct mpls_label *)addr, maxlabels);break ;default : errno =EAFNOSUPPORT ;
lib/utils.c +5 -2
@@ -518,15 +518,18 @@ int get_addr_1(inet_prefix *addr, const char *name, int family) }if (family ==AF_MPLS ) { +unsigned int maxlabels;int i; addr->family =AF_MPLS ; -if (mpls_pton (AF_MPLS , name, addr->data) <=0 ) +if (mpls_pton (AF_MPLS , name, addr->data, +sizeof (addr->data)) <=0 )return -1 ; addr->bytelen =4 ; addr->bitlen =20 ;/* How many bytes do I need? */ -for (i =0 ; i <8 ; i++) { + maxlabels =sizeof (addr->data) /sizeof (struct mpls_label ); +for (i =0 ; i < maxlabels; i++) {if (ntohl (addr->data[i]) &MPLS_LS_S_MASK ) { addr->bytelen = (i +1 )*4 ;break ;
Signature · 1 line
2.11.0 (Apple Git-81)
Quoted 73 lines · David Ahern
Kernel now supports up to 30 labels but not defined as part of the uapi. iproute2 handles up to 8 labels but in a non-consistent way. Update ip to handle more labels, but in a more programmatic way.
For the MPLS address family, the data field in
inet_prefixis used for labels. Increase that field to 64 u32's -- 64 as nothing more than a convenient power of 2 number.Update
mpls_ptonto take the length of the address field, convert that length to number of labels and add better error handling to the parsing of the user supplied string.Signed-off-by David Ahern <[email protected]>--- include/utils.h | 7 ++----- lib/mpls_pton.c | 11 +++++++---- lib/utils.c | 7 +++++-- 3 files changed, 14 insertions(+), 11 deletions(-)include/utils.h +2
-5@@ -61,7 +61,7 @@ typedef struct__s16 bitlen;/* These next two fields match rtvia */ __u16 family; -__u32 data[8 ]; +__u32 data[64 ]; } inet_prefix;#define PREFIXLEN_SPECIFIED 1@@ -88,9 +88,6 @@ struct ipx_addr {# define AF_MPLS 28#endif -/* Maximum number of labels the mpls helpers support */ -#define MPLS_MAX_LABELS 8 -__u32 get_addr32 (const char *name);int get_addr_1 (inet_prefix *dst,const char *arg,int family);int get_prefix_1 (inet_prefix *dst,char *arg,int family);@@ -155,7 +152,7 @@ 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); +int mpls_pton (int af,const char *src,void *addr,size_t alen);extern int __iproute2_hz_internal;int __get_hz (void );lib/mpls_pton.c +3
-2@@ -7,12 +7,13 @@#include "utils.h" -static int mpls_pton1 (const char *name,struct mpls_label *addr) +static int mpls_pton1 (const char *name,struct mpls_label *addr, +unsigned int maxlabels) {char *endp;unsigned count; -for (count =0 ; count <MPLS_MAX_LABELS ; count++) { +for (count =0 ; count < maxlabels; count++) {unsigned long label; label =strtoul (name, &endp,0 );@@ -37,17 +38,19 @@ static int mpls_pton1(const char *name, struct mpls_label *addr) addr +=1 ;
lib/mpls_pton.c static int mpls_pton1(const char *name, struct mpls_label *addr) · line 47
Quoted 10 lines
lib/mpls_pton.c +3
-1}/* The address was too long */ +fprintf (stderr,"Error: too many labels.\n" );return 0 ; } -int mpls_pton (int af,const char *src,void *addr) +int mpls_pton (int af,const char *src,void *addr,size_t alen) { +unsigned int maxlabels = alen /sizeof (struct mpls_label );
Could ARRAY_SIZE be used?
Also, I know its only calculated twice, but might it be nicer to provide a function or macro to do so? It seems like an ugly thing to open code.
Cosmetic points above notwithstanding:
Quoted 38 lines
lib/mpls_pton.c +1
-1int err;switch (af) {case AF_MPLS : errno =0 ; - err =mpls_pton1 (src, (struct mpls_label *)addr); + err =mpls_pton1 (src, (struct mpls_label *)addr, maxlabels);break ;default : errno =EAFNOSUPPORT ;lib/utils.c +5
-2@@ -518,15 +518,18 @@ int get_addr_1(inet_prefix *addr, const char *name, int family) }if (family ==AF_MPLS ) { +unsigned int maxlabels;int i; addr->family =AF_MPLS ; -if (mpls_pton (AF_MPLS , name, addr->data) <=0 ) +if (mpls_pton (AF_MPLS , name, addr->data, +sizeof (addr->data)) <=0 )return -1 ; addr->bytelen =4 ; addr->bitlen =20 ;/* How many bytes do I need? */ -for (i =0 ; i <8 ; i++) { + maxlabels =sizeof (addr->data) /sizeof (struct mpls_label ); +for (i =0 ; i < maxlabels; i++) {if (ntohl (addr->data[i]) &MPLS_LS_S_MASK ) { addr->bytelen = (i +1 )*4 ;break ;Signature · 1 line
2.11.0 (Apple Git-81)
Quoted 35 lines · Simon Horman
Quoted 22 lines
lib/mpls_pton.c +3
-2@@ -7,12 +7,13 @@#include "utils.h" -static int mpls_pton1 (const char *name,struct mpls_label *addr) +static int mpls_pton1 (const char *name,struct mpls_label *addr, +unsigned int maxlabels) {char *endp;unsigned count; -for (count =0 ; count <MPLS_MAX_LABELS ; count++) { +for (count =0 ; count < maxlabels; count++) {unsigned long label; label =strtoul (name, &endp,0 );@@ -37,17 +38,19 @@ static int mpls_pton1(const char *name, struct mpls_label *addr) addr +=1 ;lib/mpls_pton.c static int mpls_pton1(const char *name, struct mpls_label *addr) · line 47
Quoted 10 lines
lib/mpls_pton.c +3
-1}/* The address was too long */ +fprintf (stderr,"Error: too many labels.\n" );return 0 ; } -int mpls_pton (int af,const char *src,void *addr) +int mpls_pton (int af,const char *src,void *addr,size_t alen) { +unsigned int maxlabels = alen /sizeof (struct mpls_label );Could
ARRAY_SIZEbe used?
Quoted 3 lines
Also, I know its only calculated twice, but might it be nicer to provide a function or macro to do so? It seems like an ugly thing to open code.
I did it this way with intention -- to mpls_pton addr is just a buffer of a given length. mpls_pton converts the alen into the number of labels that the buffer can hold and passes that max to mpls_pton1 to do the heavy lifting.
Quoted 8 lines · On Sat, 13 May 2017 19:27:02 -0600 David Ahern <[email protected]> wrote:
Kernel now supports up to 30 labels but not defined as part of the uapi. iproute2 handles up to 8 labels but in a non-consistent way. Update ip to handle more labels, but in a more programmatic way.
For the MPLS address family, the data field in
inet_prefixis used for labels. Increase that field to 64 u32's -- 64 as nothing more than a convenient power of 2 number.
Quoted 5 lines
Update
mpls_ptonto take the length of the address field, convert that length to number of labels and add better error handling to the parsing of the user supplied string.Signed-off-by David Ahern <[email protected]>
Looks good applied