* [PATCH iproute2 0/3] add support for IPv6 Segment Routing
@ 2017-01-10 16:41 David Lebrun
2017-01-10 16:41 ` [PATCH iproute2 1/3] sr: add header files for SR-IPv6 David Lebrun
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw)
To: netdev; +Cc: David Lebrun
This patch series adds support for the IPv6 Segment Routing implementation in
the Linux kernel. The following features are supported.
* IPv6 SR lightweight tunnels encapsulation ("ip route add ... encap seg6 ...")
* Parsing of routes with a seg6 lwt encap ("ip route show")
* Control of internal SR structures: tunnel source ("ip sr tunsrc") and
HMAC ("ip sr hmac"). HMAC support enables to map an HMAC Key ID to
a pair of algorithm + secret.
Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
David Lebrun (3):
sr: add header files for SR-IPv6
ip: add ip sr command to control SR-IPv6 internal structures
iproute: add support for SR-IPv6 lwtunnel encapsulation
include/linux/seg6.h | 54 ++++++++++
include/linux/seg6_genl.h | 32 ++++++
include/linux/seg6_hmac.h | 21 ++++
include/linux/seg6_iptunnel.h | 38 +++++++
ip/Makefile | 2 +-
ip/ip.c | 3 +-
ip/ip_common.h | 1 +
ip/iproute.c | 6 +-
ip/iproute_lwtunnel.c | 160 ++++++++++++++++++++++++++++
ip/ipseg6.c | 238 ++++++++++++++++++++++++++++++++++++++++++
10 files changed, 551 insertions(+), 4 deletions(-)
create mode 100644 include/linux/seg6.h
create mode 100644 include/linux/seg6_genl.h
create mode 100644 include/linux/seg6_hmac.h
create mode 100644 include/linux/seg6_iptunnel.h
create mode 100644 ip/ipseg6.c
--
2.7.3
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH iproute2 1/3] sr: add header files for SR-IPv6 2017-01-10 16:41 [PATCH iproute2 0/3] add support for IPv6 Segment Routing David Lebrun @ 2017-01-10 16:41 ` David Lebrun 2017-01-10 17:25 ` Tom Herbert 2017-01-10 18:33 ` Stephen Hemminger 2017-01-10 16:41 ` [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures David Lebrun 2017-01-10 16:41 ` [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation David Lebrun 2 siblings, 2 replies; 10+ messages in thread From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw) To: netdev; +Cc: David Lebrun This patch add the necessary header files to interface with the SR-IPv6 kernel implementation. Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> --- include/linux/seg6.h | 54 +++++++++++++++++++++++++++++++++++++++++++ include/linux/seg6_genl.h | 32 +++++++++++++++++++++++++ include/linux/seg6_hmac.h | 21 +++++++++++++++++ include/linux/seg6_iptunnel.h | 38 ++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 include/linux/seg6.h create mode 100644 include/linux/seg6_genl.h create mode 100644 include/linux/seg6_hmac.h create mode 100644 include/linux/seg6_iptunnel.h diff --git a/include/linux/seg6.h b/include/linux/seg6.h new file mode 100644 index 0000000..8f651bf --- /dev/null +++ b/include/linux/seg6.h @@ -0,0 +1,54 @@ +/* + * SR-IPv6 implementation + * + * Author: + * David Lebrun <david.lebrun@uclouvain.be> + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SEG6_H +#define _SEG6_H + +/* + * SRH + */ +struct ipv6_sr_hdr { + __u8 nexthdr; + __u8 hdrlen; + __u8 type; + __u8 segments_left; + __u8 first_segment; + __u8 flag_1; + __u8 flag_2; + __u8 reserved; + + struct in6_addr segments[0]; +}; + +#define SR6_FLAG1_CLEANUP (1 << 7) +#define SR6_FLAG1_PROTECTED (1 << 6) +#define SR6_FLAG1_OAM (1 << 5) +#define SR6_FLAG1_ALERT (1 << 4) +#define SR6_FLAG1_HMAC (1 << 3) + +#define SR6_TLV_INGRESS 1 +#define SR6_TLV_EGRESS 2 +#define SR6_TLV_OPAQUE 3 +#define SR6_TLV_PADDING 4 +#define SR6_TLV_HMAC 5 + +#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP) +#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC) + +struct sr6_tlv { + __u8 type; + __u8 len; + __u8 data[0]; +}; + +#endif diff --git a/include/linux/seg6_genl.h b/include/linux/seg6_genl.h new file mode 100644 index 0000000..36fcbc8 --- /dev/null +++ b/include/linux/seg6_genl.h @@ -0,0 +1,32 @@ +#ifndef _SEG6_GENL_H +#define _SEG6_GENL_H + +#define SEG6_GENL_NAME "SEG6" +#define SEG6_GENL_VERSION 0x1 + +enum { + SEG6_ATTR_UNSPEC, + SEG6_ATTR_DST, + SEG6_ATTR_DSTLEN, + SEG6_ATTR_HMACKEYID, + SEG6_ATTR_SECRET, + SEG6_ATTR_SECRETLEN, + SEG6_ATTR_ALGID, + SEG6_ATTR_HMACINFO, + __SEG6_ATTR_MAX, +}; + +#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1) + +enum { + SEG6_CMD_UNSPEC, + SEG6_CMD_SETHMAC, + SEG6_CMD_DUMPHMAC, + SEG6_CMD_SET_TUNSRC, + SEG6_CMD_GET_TUNSRC, + __SEG6_CMD_MAX, +}; + +#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1) + +#endif diff --git a/include/linux/seg6_hmac.h b/include/linux/seg6_hmac.h new file mode 100644 index 0000000..71803d2 --- /dev/null +++ b/include/linux/seg6_hmac.h @@ -0,0 +1,21 @@ +#ifndef _SEG6_HMAC_H +#define _SEG6_HMAC_H + +#include <linux/seg6.h> + +#define SEG6_HMAC_SECRET_LEN 64 +#define SEG6_HMAC_FIELD_LEN 32 + +struct sr6_tlv_hmac { + struct sr6_tlv tlvhdr; + __u16 reserved; + __be32 hmackeyid; + __u8 hmac[SEG6_HMAC_FIELD_LEN]; +}; + +enum { + SEG6_HMAC_ALGO_SHA1 = 1, + SEG6_HMAC_ALGO_SHA256 = 2, +}; + +#endif diff --git a/include/linux/seg6_iptunnel.h b/include/linux/seg6_iptunnel.h new file mode 100644 index 0000000..0d72a58 --- /dev/null +++ b/include/linux/seg6_iptunnel.h @@ -0,0 +1,38 @@ +/* + * SR-IPv6 implementation + * + * Author: + * David Lebrun <david.lebrun@uclouvain.be> + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _SEG6_IPTUNNEL_H +#define _SEG6_IPTUNNEL_H + +#include <linux/seg6.h> + +enum { + SEG6_IPTUNNEL_UNSPEC, + SEG6_IPTUNNEL_SRH, + __SEG6_IPTUNNEL_MAX, +}; +#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1) + +struct seg6_iptunnel_encap { + int mode; + struct ipv6_sr_hdr srh[0]; +}; + +#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3)) + +enum { + SEG6_IPTUN_MODE_INLINE, + SEG6_IPTUN_MODE_ENCAP, +}; + +#endif -- 2.7.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH iproute2 1/3] sr: add header files for SR-IPv6 2017-01-10 16:41 ` [PATCH iproute2 1/3] sr: add header files for SR-IPv6 David Lebrun @ 2017-01-10 17:25 ` Tom Herbert 2017-01-10 18:33 ` Stephen Hemminger 1 sibling, 0 replies; 10+ messages in thread From: Tom Herbert @ 2017-01-10 17:25 UTC (permalink / raw) To: David Lebrun; +Cc: Linux Kernel Network Developers Acked-by: Tom Herbert <tom@herbertland.com> On Tue, Jan 10, 2017 at 8:41 AM, David Lebrun <david.lebrun@uclouvain.be> wrote: > This patch add the necessary header files to interface with the SR-IPv6 kernel > implementation. > > Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> > --- > include/linux/seg6.h | 54 +++++++++++++++++++++++++++++++++++++++++++ > include/linux/seg6_genl.h | 32 +++++++++++++++++++++++++ > include/linux/seg6_hmac.h | 21 +++++++++++++++++ > include/linux/seg6_iptunnel.h | 38 ++++++++++++++++++++++++++++++ > 4 files changed, 145 insertions(+) > create mode 100644 include/linux/seg6.h > create mode 100644 include/linux/seg6_genl.h > create mode 100644 include/linux/seg6_hmac.h > create mode 100644 include/linux/seg6_iptunnel.h > > diff --git a/include/linux/seg6.h b/include/linux/seg6.h > new file mode 100644 > index 0000000..8f651bf > --- /dev/null > +++ b/include/linux/seg6.h > @@ -0,0 +1,54 @@ > +/* > + * SR-IPv6 implementation > + * > + * Author: > + * David Lebrun <david.lebrun@uclouvain.be> > + * > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + */ > + > +#ifndef _SEG6_H > +#define _SEG6_H > + > +/* > + * SRH > + */ > +struct ipv6_sr_hdr { > + __u8 nexthdr; > + __u8 hdrlen; > + __u8 type; > + __u8 segments_left; > + __u8 first_segment; > + __u8 flag_1; > + __u8 flag_2; > + __u8 reserved; > + > + struct in6_addr segments[0]; > +}; > + > +#define SR6_FLAG1_CLEANUP (1 << 7) > +#define SR6_FLAG1_PROTECTED (1 << 6) > +#define SR6_FLAG1_OAM (1 << 5) > +#define SR6_FLAG1_ALERT (1 << 4) > +#define SR6_FLAG1_HMAC (1 << 3) > + > +#define SR6_TLV_INGRESS 1 > +#define SR6_TLV_EGRESS 2 > +#define SR6_TLV_OPAQUE 3 > +#define SR6_TLV_PADDING 4 > +#define SR6_TLV_HMAC 5 > + > +#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP) > +#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC) > + > +struct sr6_tlv { > + __u8 type; > + __u8 len; > + __u8 data[0]; > +}; > + > +#endif > diff --git a/include/linux/seg6_genl.h b/include/linux/seg6_genl.h > new file mode 100644 > index 0000000..36fcbc8 > --- /dev/null > +++ b/include/linux/seg6_genl.h > @@ -0,0 +1,32 @@ > +#ifndef _SEG6_GENL_H > +#define _SEG6_GENL_H > + > +#define SEG6_GENL_NAME "SEG6" > +#define SEG6_GENL_VERSION 0x1 > + > +enum { > + SEG6_ATTR_UNSPEC, > + SEG6_ATTR_DST, > + SEG6_ATTR_DSTLEN, > + SEG6_ATTR_HMACKEYID, > + SEG6_ATTR_SECRET, > + SEG6_ATTR_SECRETLEN, > + SEG6_ATTR_ALGID, > + SEG6_ATTR_HMACINFO, > + __SEG6_ATTR_MAX, > +}; > + > +#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1) > + > +enum { > + SEG6_CMD_UNSPEC, > + SEG6_CMD_SETHMAC, > + SEG6_CMD_DUMPHMAC, > + SEG6_CMD_SET_TUNSRC, > + SEG6_CMD_GET_TUNSRC, > + __SEG6_CMD_MAX, > +}; > + > +#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1) > + > +#endif > diff --git a/include/linux/seg6_hmac.h b/include/linux/seg6_hmac.h > new file mode 100644 > index 0000000..71803d2 > --- /dev/null > +++ b/include/linux/seg6_hmac.h > @@ -0,0 +1,21 @@ > +#ifndef _SEG6_HMAC_H > +#define _SEG6_HMAC_H > + > +#include <linux/seg6.h> > + > +#define SEG6_HMAC_SECRET_LEN 64 > +#define SEG6_HMAC_FIELD_LEN 32 > + > +struct sr6_tlv_hmac { > + struct sr6_tlv tlvhdr; > + __u16 reserved; > + __be32 hmackeyid; > + __u8 hmac[SEG6_HMAC_FIELD_LEN]; > +}; > + > +enum { > + SEG6_HMAC_ALGO_SHA1 = 1, > + SEG6_HMAC_ALGO_SHA256 = 2, > +}; > + > +#endif > diff --git a/include/linux/seg6_iptunnel.h b/include/linux/seg6_iptunnel.h > new file mode 100644 > index 0000000..0d72a58 > --- /dev/null > +++ b/include/linux/seg6_iptunnel.h > @@ -0,0 +1,38 @@ > +/* > + * SR-IPv6 implementation > + * > + * Author: > + * David Lebrun <david.lebrun@uclouvain.be> > + * > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version > + * 2 of the License, or (at your option) any later version. > + */ > + > +#ifndef _SEG6_IPTUNNEL_H > +#define _SEG6_IPTUNNEL_H > + > +#include <linux/seg6.h> > + > +enum { > + SEG6_IPTUNNEL_UNSPEC, > + SEG6_IPTUNNEL_SRH, > + __SEG6_IPTUNNEL_MAX, > +}; > +#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1) > + > +struct seg6_iptunnel_encap { > + int mode; > + struct ipv6_sr_hdr srh[0]; > +}; > + > +#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3)) > + > +enum { > + SEG6_IPTUN_MODE_INLINE, > + SEG6_IPTUN_MODE_ENCAP, > +}; > + > +#endif > -- > 2.7.3 > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH iproute2 1/3] sr: add header files for SR-IPv6 2017-01-10 16:41 ` [PATCH iproute2 1/3] sr: add header files for SR-IPv6 David Lebrun 2017-01-10 17:25 ` Tom Herbert @ 2017-01-10 18:33 ` Stephen Hemminger 2017-01-12 8:35 ` David Lebrun 1 sibling, 1 reply; 10+ messages in thread From: Stephen Hemminger @ 2017-01-10 18:33 UTC (permalink / raw) To: David Lebrun; +Cc: netdev On Tue, 10 Jan 2017 17:41:24 +0100 David Lebrun <david.lebrun@uclouvain.be> wrote: > This patch add the necessary header files to interface with the SR-IPv6 kernel > implementation. > > Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> > --- > include/linux/seg6.h | 54 +++++++++++++++++++++++++++++++++++++++++++ > include/linux/seg6_genl.h | 32 +++++++++++++++++++++++++ > include/linux/seg6_hmac.h | 21 +++++++++++++++++ > include/linux/seg6_iptunnel.h | 38 ++++++++++++++++++++++++++++++ > 4 files changed, 145 insertions(+) > create mode 100644 include/linux/seg6.h > create mode 100644 include/linux/seg6_genl.h > create mode 100644 include/linux/seg6_hmac.h > create mode 100644 include/linux/seg6_iptunnel.h I get all headers from santized kernel headers generated by $ make headers_install but the segmentation stuff is missing. When you added segment routing headers you forgot to export them. Please send a patch to include/uapi/linux/Kbuild, after that is merged I will pick them up. Also this patch is only for net-next. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH iproute2 1/3] sr: add header files for SR-IPv6 2017-01-10 18:33 ` Stephen Hemminger @ 2017-01-12 8:35 ` David Lebrun 0 siblings, 0 replies; 10+ messages in thread From: David Lebrun @ 2017-01-12 8:35 UTC (permalink / raw) To: Stephen Hemminger; +Cc: netdev [-- Attachment #1: Type: text/plain, Size: 441 bytes --] On 01/10/2017 07:33 PM, Stephen Hemminger wrote: > I get all headers from santized kernel headers generated by > $ make headers_install > but the segmentation stuff is missing. > > When you added segment routing headers you forgot to export them. > Please send a patch to include/uapi/linux/Kbuild, after that is merged > I will pick them up. > > Also this patch is only for net-next. Oops ! Will do that, thanks David [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 163 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures 2017-01-10 16:41 [PATCH iproute2 0/3] add support for IPv6 Segment Routing David Lebrun 2017-01-10 16:41 ` [PATCH iproute2 1/3] sr: add header files for SR-IPv6 David Lebrun @ 2017-01-10 16:41 ` David Lebrun 2017-01-10 17:25 ` Tom Herbert 2017-01-10 18:35 ` Stephen Hemminger 2017-01-10 16:41 ` [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation David Lebrun 2 siblings, 2 replies; 10+ messages in thread From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw) To: netdev; +Cc: David Lebrun This patch add commands to support the tunnel source properties ("ip sr tunsrc") and the HMAC key -> secret, algorithm binding ("ip sr hmac"). Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> --- ip/Makefile | 2 +- ip/ip.c | 3 +- ip/ip_common.h | 1 + ip/ipseg6.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 ip/ipseg6.c diff --git a/ip/Makefile b/ip/Makefile index 1928489..678a795 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -8,7 +8,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ - ipvrf.o + ipvrf.o ipseg6.o RTMONOBJ=rtmon.o diff --git a/ip/ip.c b/ip/ip.c index 07050b0..7c14a8e 100644 --- a/ip/ip.c +++ b/ip/ip.c @@ -52,7 +52,7 @@ static void usage(void) "where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" " netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n" -" vrf }\n" +" vrf | sr }\n" " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -h[uman-readable] | -iec |\n" " -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n" @@ -101,6 +101,7 @@ static const struct cmd { { "netns", do_netns }, { "netconf", do_ipnetconf }, { "vrf", do_ipvrf}, + { "sr", do_seg6 }, { "help", do_help }, { 0 } }; diff --git a/ip/ip_common.h b/ip/ip_common.h index ab6a834..13108c6 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -59,6 +59,7 @@ int do_ipnetconf(int argc, char **argv); int do_iptoken(int argc, char **argv); int do_ipvrf(int argc, char **argv); void vrf_reset(void); +int do_seg6(int argc, char **argv); int iplink_get(unsigned int flags, char *name, __u32 filt_mask); diff --git a/ip/ipseg6.c b/ip/ipseg6.c new file mode 100644 index 0000000..0d4130e --- /dev/null +++ b/ip/ipseg6.c @@ -0,0 +1,238 @@ +/* + * seg6.c "ip sr/seg6" + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation; + * + * Author: David Lebrun <david.lebrun@uclouvain.be> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> +#include <linux/if.h> + +#include <linux/genetlink.h> +#include <linux/seg6_genl.h> +#include <linux/seg6_hmac.h> + +#include "utils.h" +#include "ip_common.h" +#include "libgenl.h" + +#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): " + +static void usage(void) +{ + fprintf(stderr, "Usage: ip sr { COMMAND | help }\n"); + fprintf(stderr, " ip sr hmac show\n"); + fprintf(stderr, " ip sr hmac set KEYID ALGO\n"); + fprintf(stderr, " ip sr tunsrc show\n"); + fprintf(stderr, " ip sr tunsrc set ADDRESS\n"); + fprintf(stderr, "where ALGO := { sha1 | sha256 }\n"); + exit(-1); +} + +static struct rtnl_handle grth = { .fd = -1 }; +static int genl_family = -1; + +#define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \ + GENL_REQUEST(_req, _bufsiz, genl_family, 0, \ + SEG6_GENL_VERSION, _cmd, _flags) + +static struct { + int cmd; + struct in6_addr addr; + __u32 keyid; + char *pass; + __u8 alg_id; +} opts; + +static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, + void *arg) +{ + struct rtattr *attrs[SEG6_ATTR_MAX + 1]; + struct genlmsghdr *ghdr; + FILE *fp = (FILE *)arg; + int len = n->nlmsg_len; + + if (n->nlmsg_type != genl_family) + return -1; + + len -= NLMSG_LENGTH(GENL_HDRLEN); + if (len < 0) + return -1; + + ghdr = NLMSG_DATA(n); + + parse_rtattr(attrs, SEG6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len); + + switch (ghdr->cmd) { + case SEG6_CMD_DUMPHMAC: + { + char secret[64]; + char *algstr; + __u8 slen = rta_getattr_u8(attrs[SEG6_ATTR_SECRETLEN]); + __u8 alg_id = rta_getattr_u8(attrs[SEG6_ATTR_ALGID]); + + memset(secret, 0, 64); + + if (slen > 63) { + fprintf(stderr, "HMAC secret length %d > 63, " + "truncated\n", slen); + slen = 63; + } + memcpy(secret, RTA_DATA(attrs[SEG6_ATTR_SECRET]), slen); + + switch (alg_id) { + case SEG6_HMAC_ALGO_SHA1: + algstr = "sha1"; + break; + case SEG6_HMAC_ALGO_SHA256: + algstr = "sha256"; + break; + default: + algstr = "<unknown>"; + } + + fprintf(fp, "hmac %u ", + rta_getattr_u32(attrs[SEG6_ATTR_HMACKEYID])); + fprintf(fp, "algo %s ", algstr); + fprintf(fp, "secret \"%s\" ", secret); + + fprintf(fp, "\n"); + break; + } + case SEG6_CMD_GET_TUNSRC: + { + fprintf(fp, "tunsrc addr %s\n", + rt_addr_n2a(AF_INET6, 16, + RTA_DATA(attrs[SEG6_ATTR_DST]))); + break; + } + } + + return 0; +} + +static int seg6_do_cmd(void) +{ + SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST); + int repl = 0, dump = 0; + + if (genl_family < 0) { + if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) { + fprintf(stderr, "Cannot open generic netlink socket\n"); + exit(1); + } + genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME); + if (genl_family < 0) + exit(1); + req.n.nlmsg_type = genl_family; + } + + switch (opts.cmd) { + case SEG6_CMD_SETHMAC: + { + addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid); + addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN, + strlen(opts.pass)); + addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id); + if (strlen(opts.pass)) + addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET, + opts.pass, strlen(opts.pass)); + break; + } + case SEG6_CMD_SET_TUNSRC: + addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, &opts.addr, + sizeof(struct in6_addr)); + break; + case SEG6_CMD_DUMPHMAC: + dump = 1; + break; + case SEG6_CMD_GET_TUNSRC: + repl = 1; + break; + } + + if (!repl && !dump) { + if (rtnl_talk(&grth, &req.n, NULL, 0) < 0) + return -1; + } else if (repl) { + if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0) + return -2; + if (process_msg(NULL, &req.n, stdout) < 0) { + fprintf(stderr, "Error parsing reply\n"); + exit(1); + } + } else { + req.n.nlmsg_flags |= NLM_F_DUMP; + req.n.nlmsg_seq = grth.dump = ++grth.seq; + if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) { + perror("Failed to send dump request"); + exit(1); + } + + if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) { + fprintf(stderr, "Dump terminated\n"); + exit(1); + } + } + + return 0; +} + +int do_seg6(int argc, char **argv) +{ + if (argc < 1 || matches(*argv, "help") == 0) + usage(); + + memset(&opts, 0, sizeof(opts)); + + if (matches(*argv, "hmac") == 0) { + NEXT_ARG(); + if (matches(*argv, "show") == 0) { + opts.cmd = SEG6_CMD_DUMPHMAC; + } else if (matches(*argv, "set") == 0) { + NEXT_ARG(); + if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0) + invarg("hmac KEYID value is invalid", *argv); + NEXT_ARG(); + if (strcmp(*argv, "sha1") == 0) { + opts.alg_id = SEG6_HMAC_ALGO_SHA1; + } else if (strcmp(*argv, "sha256") == 0) { + opts.alg_id = SEG6_HMAC_ALGO_SHA256; + } else { + invarg("hmac ALGO value is invalid", *argv); + } + opts.cmd = SEG6_CMD_SETHMAC; + opts.pass = getpass(HMAC_KEY_PROMPT); + } else { + invarg("unknown", *argv); + } + } else if (matches(*argv, "tunsrc") == 0) { + NEXT_ARG(); + if (matches(*argv, "show") == 0) { + opts.cmd = SEG6_CMD_GET_TUNSRC; + } else if (matches(*argv, "set") == 0) { + NEXT_ARG(); + opts.cmd = SEG6_CMD_SET_TUNSRC; + if (!inet_get_addr(*argv, NULL, &opts.addr)) + invarg("tunsrc ADDRESS value is invalid", + *argv); + } else { + invarg("unknown", *argv); + } + } else { + invarg("unknown", *argv); + } + + return seg6_do_cmd(); +} -- 2.7.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures 2017-01-10 16:41 ` [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures David Lebrun @ 2017-01-10 17:25 ` Tom Herbert 2017-01-10 18:35 ` Stephen Hemminger 1 sibling, 0 replies; 10+ messages in thread From: Tom Herbert @ 2017-01-10 17:25 UTC (permalink / raw) To: David Lebrun; +Cc: Linux Kernel Network Developers On Tue, Jan 10, 2017 at 8:41 AM, David Lebrun <david.lebrun@uclouvain.be> wrote: > This patch add commands to support the tunnel source properties > ("ip sr tunsrc") and the HMAC key -> secret, algorithm binding > ("ip sr hmac"). > > Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> > --- > ip/Makefile | 2 +- > ip/ip.c | 3 +- > ip/ip_common.h | 1 + > ip/ipseg6.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 242 insertions(+), 2 deletions(-) > create mode 100644 ip/ipseg6.c > > diff --git a/ip/Makefile b/ip/Makefile > index 1928489..678a795 100644 > --- a/ip/Makefile > +++ b/ip/Makefile > @@ -8,7 +8,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ > link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ > iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ > iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ > - ipvrf.o > + ipvrf.o ipseg6.o > > RTMONOBJ=rtmon.o > > diff --git a/ip/ip.c b/ip/ip.c > index 07050b0..7c14a8e 100644 > --- a/ip/ip.c > +++ b/ip/ip.c > @@ -52,7 +52,7 @@ static void usage(void) > "where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n" > " tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n" > " netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n" > -" vrf }\n" > +" vrf | sr }\n" > " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" > " -h[uman-readable] | -iec |\n" > " -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n" > @@ -101,6 +101,7 @@ static const struct cmd { > { "netns", do_netns }, > { "netconf", do_ipnetconf }, > { "vrf", do_ipvrf}, > + { "sr", do_seg6 }, > { "help", do_help }, > { 0 } > }; > diff --git a/ip/ip_common.h b/ip/ip_common.h > index ab6a834..13108c6 100644 > --- a/ip/ip_common.h > +++ b/ip/ip_common.h > @@ -59,6 +59,7 @@ int do_ipnetconf(int argc, char **argv); > int do_iptoken(int argc, char **argv); > int do_ipvrf(int argc, char **argv); > void vrf_reset(void); > +int do_seg6(int argc, char **argv); > > int iplink_get(unsigned int flags, char *name, __u32 filt_mask); > > diff --git a/ip/ipseg6.c b/ip/ipseg6.c > new file mode 100644 > index 0000000..0d4130e > --- /dev/null > +++ b/ip/ipseg6.c > @@ -0,0 +1,238 @@ > +/* > + * seg6.c "ip sr/seg6" > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * version 2 as published by the Free Software Foundation; > + * > + * Author: David Lebrun <david.lebrun@uclouvain.be> > + */ > + > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <unistd.h> > +#include <errno.h> > +#include <sys/types.h> > +#include <sys/socket.h> > +#include <arpa/inet.h> > +#include <sys/ioctl.h> > +#include <linux/if.h> > + > +#include <linux/genetlink.h> > +#include <linux/seg6_genl.h> > +#include <linux/seg6_hmac.h> > + > +#include "utils.h" > +#include "ip_common.h" > +#include "libgenl.h" > + > +#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): " > + > +static void usage(void) > +{ > + fprintf(stderr, "Usage: ip sr { COMMAND | help }\n"); > + fprintf(stderr, " ip sr hmac show\n"); > + fprintf(stderr, " ip sr hmac set KEYID ALGO\n"); > + fprintf(stderr, " ip sr tunsrc show\n"); > + fprintf(stderr, " ip sr tunsrc set ADDRESS\n"); > + fprintf(stderr, "where ALGO := { sha1 | sha256 }\n"); > + exit(-1); > +} > + > +static struct rtnl_handle grth = { .fd = -1 }; > +static int genl_family = -1; > + > +#define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \ > + GENL_REQUEST(_req, _bufsiz, genl_family, 0, \ > + SEG6_GENL_VERSION, _cmd, _flags) > + > +static struct { > + int cmd; > + struct in6_addr addr; > + __u32 keyid; > + char *pass; > + __u8 alg_id; > +} opts; > + > +static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, > + void *arg) > +{ > + struct rtattr *attrs[SEG6_ATTR_MAX + 1]; > + struct genlmsghdr *ghdr; > + FILE *fp = (FILE *)arg; > + int len = n->nlmsg_len; > + > + if (n->nlmsg_type != genl_family) > + return -1; > + > + len -= NLMSG_LENGTH(GENL_HDRLEN); > + if (len < 0) > + return -1; > + > + ghdr = NLMSG_DATA(n); > + > + parse_rtattr(attrs, SEG6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len); > + > + switch (ghdr->cmd) { > + case SEG6_CMD_DUMPHMAC: > + { > + char secret[64]; > + char *algstr; > + __u8 slen = rta_getattr_u8(attrs[SEG6_ATTR_SECRETLEN]); > + __u8 alg_id = rta_getattr_u8(attrs[SEG6_ATTR_ALGID]); > + > + memset(secret, 0, 64); > + > + if (slen > 63) { > + fprintf(stderr, "HMAC secret length %d > 63, " > + "truncated\n", slen); > + slen = 63; > + } > + memcpy(secret, RTA_DATA(attrs[SEG6_ATTR_SECRET]), slen); > + > + switch (alg_id) { > + case SEG6_HMAC_ALGO_SHA1: > + algstr = "sha1"; > + break; > + case SEG6_HMAC_ALGO_SHA256: > + algstr = "sha256"; > + break; > + default: > + algstr = "<unknown>"; > + } > + > + fprintf(fp, "hmac %u ", > + rta_getattr_u32(attrs[SEG6_ATTR_HMACKEYID])); > + fprintf(fp, "algo %s ", algstr); > + fprintf(fp, "secret \"%s\" ", secret); > + > + fprintf(fp, "\n"); > + break; > + } > + case SEG6_CMD_GET_TUNSRC: > + { > + fprintf(fp, "tunsrc addr %s\n", > + rt_addr_n2a(AF_INET6, 16, > + RTA_DATA(attrs[SEG6_ATTR_DST]))); > + break; > + } > + } > + > + return 0; > +} > + > +static int seg6_do_cmd(void) > +{ > + SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST); > + int repl = 0, dump = 0; > + > + if (genl_family < 0) { > + if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) { > + fprintf(stderr, "Cannot open generic netlink socket\n"); > + exit(1); > + } > + genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME); > + if (genl_family < 0) > + exit(1); > + req.n.nlmsg_type = genl_family; > + } > + > + switch (opts.cmd) { > + case SEG6_CMD_SETHMAC: > + { > + addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid); > + addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN, > + strlen(opts.pass)); > + addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id); > + if (strlen(opts.pass)) > + addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET, > + opts.pass, strlen(opts.pass)); > + break; > + } > + case SEG6_CMD_SET_TUNSRC: > + addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, &opts.addr, > + sizeof(struct in6_addr)); > + break; > + case SEG6_CMD_DUMPHMAC: > + dump = 1; > + break; > + case SEG6_CMD_GET_TUNSRC: > + repl = 1; > + break; > + } > + > + if (!repl && !dump) { > + if (rtnl_talk(&grth, &req.n, NULL, 0) < 0) > + return -1; > + } else if (repl) { > + if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0) > + return -2; > + if (process_msg(NULL, &req.n, stdout) < 0) { > + fprintf(stderr, "Error parsing reply\n"); > + exit(1); > + } > + } else { > + req.n.nlmsg_flags |= NLM_F_DUMP; > + req.n.nlmsg_seq = grth.dump = ++grth.seq; > + if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) { > + perror("Failed to send dump request"); > + exit(1); > + } > + > + if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) { > + fprintf(stderr, "Dump terminated\n"); > + exit(1); > + } > + } > + > + return 0; > +} > + > +int do_seg6(int argc, char **argv) > +{ > + if (argc < 1 || matches(*argv, "help") == 0) > + usage(); > + > + memset(&opts, 0, sizeof(opts)); > + > + if (matches(*argv, "hmac") == 0) { > + NEXT_ARG(); > + if (matches(*argv, "show") == 0) { > + opts.cmd = SEG6_CMD_DUMPHMAC; > + } else if (matches(*argv, "set") == 0) { > + NEXT_ARG(); > + if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0) > + invarg("hmac KEYID value is invalid", *argv); > + NEXT_ARG(); > + if (strcmp(*argv, "sha1") == 0) { > + opts.alg_id = SEG6_HMAC_ALGO_SHA1; > + } else if (strcmp(*argv, "sha256") == 0) { > + opts.alg_id = SEG6_HMAC_ALGO_SHA256; > + } else { > + invarg("hmac ALGO value is invalid", *argv); > + } > + opts.cmd = SEG6_CMD_SETHMAC; > + opts.pass = getpass(HMAC_KEY_PROMPT); > + } else { > + invarg("unknown", *argv); > + } > + } else if (matches(*argv, "tunsrc") == 0) { > + NEXT_ARG(); > + if (matches(*argv, "show") == 0) { > + opts.cmd = SEG6_CMD_GET_TUNSRC; > + } else if (matches(*argv, "set") == 0) { > + NEXT_ARG(); > + opts.cmd = SEG6_CMD_SET_TUNSRC; > + if (!inet_get_addr(*argv, NULL, &opts.addr)) > + invarg("tunsrc ADDRESS value is invalid", > + *argv); > + } else { > + invarg("unknown", *argv); > + } > + } else { > + invarg("unknown", *argv); > + } > + > + return seg6_do_cmd(); > +} > -- > 2.7.3 > Acked-by: Tom Herbert <tom@herbertland.com> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures 2017-01-10 16:41 ` [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures David Lebrun 2017-01-10 17:25 ` Tom Herbert @ 2017-01-10 18:35 ` Stephen Hemminger 1 sibling, 0 replies; 10+ messages in thread From: Stephen Hemminger @ 2017-01-10 18:35 UTC (permalink / raw) To: David Lebrun; +Cc: netdev On Tue, 10 Jan 2017 17:41:25 +0100 David Lebrun <david.lebrun@uclouvain.be> wrote: > This patch add commands to support the tunnel source properties > ("ip sr tunsrc") and the HMAC key -> secret, algorithm binding > ("ip sr hmac"). > > Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> > --- Man page? ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation 2017-01-10 16:41 [PATCH iproute2 0/3] add support for IPv6 Segment Routing David Lebrun 2017-01-10 16:41 ` [PATCH iproute2 1/3] sr: add header files for SR-IPv6 David Lebrun 2017-01-10 16:41 ` [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures David Lebrun @ 2017-01-10 16:41 ` David Lebrun 2017-01-10 17:26 ` Tom Herbert 2 siblings, 1 reply; 10+ messages in thread From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw) To: netdev; +Cc: David Lebrun This patch adds support for SEG6 encapsulation type ("ip route add ... encap seg6 ..."). Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> --- ip/iproute.c | 6 +- ip/iproute_lwtunnel.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 2 deletions(-) diff --git a/ip/iproute.c b/ip/iproute.c index e433de8..a102e33 100644 --- a/ip/iproute.c +++ b/ip/iproute.c @@ -98,8 +98,10 @@ static void usage(void) fprintf(stderr, "TIME := NUMBER[s|ms]\n"); fprintf(stderr, "BOOL := [1|0]\n"); fprintf(stderr, "FEATURES := ecn\n"); - fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n"); - fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n"); + fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 | seg6 ]\n"); + fprintf(stderr, "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n"); + fprintf(stderr, "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n"); + fprintf(stderr, "SEGMODE := [ encap | inline ]\n"); exit(-1); } diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 1a92cec..3ee6dcc 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -26,6 +26,10 @@ #include "iproute_lwtunnel.h" #include "bpf_util.h" +#include <linux/seg6.h> +#include <linux/seg6_iptunnel.h> +#include <linux/seg6_hmac.h> + static const char *format_encap_type(int type) { switch (type) { @@ -39,6 +43,8 @@ static const char *format_encap_type(int type) return "ila"; case LWTUNNEL_ENCAP_BPF: return "bpf"; + case LWTUNNEL_ENCAP_SEG6: + return "seg6"; default: return "unknown"; } @@ -69,12 +75,51 @@ static int read_encap_type(const char *name) return LWTUNNEL_ENCAP_ILA; else if (strcmp(name, "bpf") == 0) return LWTUNNEL_ENCAP_BPF; + else if (strcmp(name, "seg6") == 0) + return LWTUNNEL_ENCAP_SEG6; else if (strcmp(name, "help") == 0) encap_type_usage(); return LWTUNNEL_ENCAP_NONE; } +static void print_encap_seg6(FILE *fp, struct rtattr *encap) +{ + struct rtattr *tb[SEG6_IPTUNNEL_MAX+1]; + struct seg6_iptunnel_encap *tuninfo; + struct ipv6_sr_hdr *srh; + int i; + + parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap); + + if (!tb[SEG6_IPTUNNEL_SRH]) + return; + + tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]); + fprintf(fp, "mode %s ", + (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP) ? "encap" : "inline"); + + srh = tuninfo->srh; + + fprintf(fp, "segs %d [ ", srh->first_segment + 1); + + for (i = srh->first_segment; i >= 0; i--) + fprintf(fp, "%s ", + rt_addr_n2a(AF_INET6, 16, &srh->segments[i])); + + fprintf(fp, "] "); + + if (sr_has_cleanup(srh)) + + if (sr_has_hmac(srh)) { + unsigned int offset = ((srh->hdrlen + 1) << 3) - 40; + struct sr6_tlv_hmac *tlv; + + tlv = (struct sr6_tlv_hmac *)((char *)srh + offset); + fprintf(fp, "hmac 0x%X ", ntohl(tlv->hmackeyid)); + } +} + static void print_encap_mpls(FILE *fp, struct rtattr *encap) { struct rtattr *tb[MPLS_IPTUNNEL_MAX+1]; @@ -238,9 +283,121 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type, case LWTUNNEL_ENCAP_BPF: print_encap_bpf(fp, encap); break; + case LWTUNNEL_ENCAP_SEG6: + print_encap_seg6(fp, encap); + break; } } +static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, + char ***argvp) +{ + int mode_ok = 0, segs_ok = 0, cleanup_ok = 0, hmac_ok = 0; + struct seg6_iptunnel_encap *tuninfo; + struct ipv6_sr_hdr *srh; + char **argv = *argvp; + char segbuf[1024]; + int argc = *argcp; + __u8 cleanup = 0; + int encap = -1; + __u32 hmac = 0; + int nsegs = 0; + int srhlen; + char *s; + int i; + + while (argc > 0) { + if (strcmp(*argv, "mode") == 0) { + NEXT_ARG(); + if (mode_ok++) + duparg2("mode", *argv); + if (strcmp(*argv, "encap") == 0) + encap = 1; + else if (strcmp(*argv, "inline") == 0) + encap = 0; + else + invarg("\"mode\" value is invalid\n", *argv); + } else if (strcmp(*argv, "segs") == 0) { + NEXT_ARG(); + if (segs_ok++) + duparg2("segs", *argv); + if (encap == -1) + invarg("\"segs\" provided before \"mode\"\n", + *argv); + + strncpy(segbuf, *argv, 1024); + segbuf[1023] = 0; + } else if (strcmp(*argv, "cleanup") == 0) { + if (cleanup_ok++) + duparg2("cleanup", *argv); + cleanup = 1; + } else if (strcmp(*argv, "hmac") == 0) { + NEXT_ARG(); + if (hmac_ok++) + duparg2("hmac", *argv); + get_u32(&hmac, *argv, 0); + } else { + break; + } + argc--; argv++; + } + + s = segbuf; + for (i = 0; *s; *s++ == ',' ? i++ : *s); + nsegs = i + 1; + + if (!encap) + nsegs++; + + srhlen = 8 + 16*nsegs; + + if (hmac) + srhlen += 40; + + tuninfo = malloc(sizeof(*tuninfo) + srhlen); + memset(tuninfo, 0, sizeof(*tuninfo) + srhlen); + + if (encap) + tuninfo->mode = SEG6_IPTUN_MODE_ENCAP; + else + tuninfo->mode = SEG6_IPTUN_MODE_INLINE; + + srh = tuninfo->srh; + srh->hdrlen = (srhlen >> 3) - 1; + srh->type = 4; + srh->segments_left = nsegs - 1; + srh->first_segment = nsegs - 1; + + if (cleanup) + srh->flag_1 |= SR6_FLAG1_CLEANUP; + if (hmac) + srh->flag_1 |= SR6_FLAG1_HMAC; + + i = srh->first_segment; + for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) { + inet_get_addr(s, NULL, &srh->segments[i]); + i--; + } + + if (hmac) { + struct sr6_tlv_hmac *tlv; + + tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40); + tlv->tlvhdr.type = SR6_TLV_HMAC; + tlv->tlvhdr.len = 38; + tlv->hmackeyid = htonl(hmac); + } + + rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, + sizeof(*tuninfo) + srhlen); + free(tuninfo); + + *argcp = argc + 1; + *argvp = argv - 1; + + return 0; +} + static int parse_encap_mpls(struct rtattr *rta, size_t len, int *argcp, char ***argvp) { @@ -573,6 +730,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) if (parse_encap_bpf(rta, len, &argc, &argv) < 0) exit(-1); break; + case LWTUNNEL_ENCAP_SEG6: + parse_encap_seg6(rta, len, &argc, &argv); + break; default: fprintf(stderr, "Error: unsupported encap type\n"); break; -- 2.7.3 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation 2017-01-10 16:41 ` [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation David Lebrun @ 2017-01-10 17:26 ` Tom Herbert 0 siblings, 0 replies; 10+ messages in thread From: Tom Herbert @ 2017-01-10 17:26 UTC (permalink / raw) To: David Lebrun; +Cc: Linux Kernel Network Developers On Tue, Jan 10, 2017 at 8:41 AM, David Lebrun <david.lebrun@uclouvain.be> wrote: > This patch adds support for SEG6 encapsulation type > ("ip route add ... encap seg6 ..."). > > Signed-off-by: David Lebrun <david.lebrun@uclouvain.be> > --- > ip/iproute.c | 6 +- > ip/iproute_lwtunnel.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 164 insertions(+), 2 deletions(-) > > diff --git a/ip/iproute.c b/ip/iproute.c > index e433de8..a102e33 100644 > --- a/ip/iproute.c > +++ b/ip/iproute.c > @@ -98,8 +98,10 @@ static void usage(void) > fprintf(stderr, "TIME := NUMBER[s|ms]\n"); > fprintf(stderr, "BOOL := [1|0]\n"); > fprintf(stderr, "FEATURES := ecn\n"); > - fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n"); > - fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n"); > + fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 | seg6 ]\n"); > + fprintf(stderr, "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n"); > + fprintf(stderr, "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n"); > + fprintf(stderr, "SEGMODE := [ encap | inline ]\n"); > exit(-1); > } > > diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c > index 1a92cec..3ee6dcc 100644 > --- a/ip/iproute_lwtunnel.c > +++ b/ip/iproute_lwtunnel.c > @@ -26,6 +26,10 @@ > #include "iproute_lwtunnel.h" > #include "bpf_util.h" > > +#include <linux/seg6.h> > +#include <linux/seg6_iptunnel.h> > +#include <linux/seg6_hmac.h> > + > static const char *format_encap_type(int type) > { > switch (type) { > @@ -39,6 +43,8 @@ static const char *format_encap_type(int type) > return "ila"; > case LWTUNNEL_ENCAP_BPF: > return "bpf"; > + case LWTUNNEL_ENCAP_SEG6: > + return "seg6"; > default: > return "unknown"; > } > @@ -69,12 +75,51 @@ static int read_encap_type(const char *name) > return LWTUNNEL_ENCAP_ILA; > else if (strcmp(name, "bpf") == 0) > return LWTUNNEL_ENCAP_BPF; > + else if (strcmp(name, "seg6") == 0) > + return LWTUNNEL_ENCAP_SEG6; > else if (strcmp(name, "help") == 0) > encap_type_usage(); > > return LWTUNNEL_ENCAP_NONE; > } > > +static void print_encap_seg6(FILE *fp, struct rtattr *encap) > +{ > + struct rtattr *tb[SEG6_IPTUNNEL_MAX+1]; > + struct seg6_iptunnel_encap *tuninfo; > + struct ipv6_sr_hdr *srh; > + int i; > + > + parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap); > + > + if (!tb[SEG6_IPTUNNEL_SRH]) > + return; > + > + tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]); > + fprintf(fp, "mode %s ", > + (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP) ? "encap" : "inline"); > + > + srh = tuninfo->srh; > + > + fprintf(fp, "segs %d [ ", srh->first_segment + 1); > + > + for (i = srh->first_segment; i >= 0; i--) > + fprintf(fp, "%s ", > + rt_addr_n2a(AF_INET6, 16, &srh->segments[i])); > + > + fprintf(fp, "] "); > + > + if (sr_has_cleanup(srh)) > + > + if (sr_has_hmac(srh)) { > + unsigned int offset = ((srh->hdrlen + 1) << 3) - 40; > + struct sr6_tlv_hmac *tlv; > + > + tlv = (struct sr6_tlv_hmac *)((char *)srh + offset); > + fprintf(fp, "hmac 0x%X ", ntohl(tlv->hmackeyid)); > + } > +} > + > static void print_encap_mpls(FILE *fp, struct rtattr *encap) > { > struct rtattr *tb[MPLS_IPTUNNEL_MAX+1]; > @@ -238,9 +283,121 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type, > case LWTUNNEL_ENCAP_BPF: > print_encap_bpf(fp, encap); > break; > + case LWTUNNEL_ENCAP_SEG6: > + print_encap_seg6(fp, encap); > + break; > } > } > > +static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp, > + char ***argvp) > +{ > + int mode_ok = 0, segs_ok = 0, cleanup_ok = 0, hmac_ok = 0; > + struct seg6_iptunnel_encap *tuninfo; > + struct ipv6_sr_hdr *srh; > + char **argv = *argvp; > + char segbuf[1024]; > + int argc = *argcp; > + __u8 cleanup = 0; > + int encap = -1; > + __u32 hmac = 0; > + int nsegs = 0; > + int srhlen; > + char *s; > + int i; > + > + while (argc > 0) { > + if (strcmp(*argv, "mode") == 0) { > + NEXT_ARG(); > + if (mode_ok++) > + duparg2("mode", *argv); > + if (strcmp(*argv, "encap") == 0) > + encap = 1; > + else if (strcmp(*argv, "inline") == 0) > + encap = 0; > + else > + invarg("\"mode\" value is invalid\n", *argv); > + } else if (strcmp(*argv, "segs") == 0) { > + NEXT_ARG(); > + if (segs_ok++) > + duparg2("segs", *argv); > + if (encap == -1) > + invarg("\"segs\" provided before \"mode\"\n", > + *argv); > + > + strncpy(segbuf, *argv, 1024); > + segbuf[1023] = 0; > + } else if (strcmp(*argv, "cleanup") == 0) { > + if (cleanup_ok++) > + duparg2("cleanup", *argv); > + cleanup = 1; > + } else if (strcmp(*argv, "hmac") == 0) { > + NEXT_ARG(); > + if (hmac_ok++) > + duparg2("hmac", *argv); > + get_u32(&hmac, *argv, 0); > + } else { > + break; > + } > + argc--; argv++; > + } > + > + s = segbuf; > + for (i = 0; *s; *s++ == ',' ? i++ : *s); > + nsegs = i + 1; > + > + if (!encap) > + nsegs++; > + > + srhlen = 8 + 16*nsegs; > + > + if (hmac) > + srhlen += 40; > + > + tuninfo = malloc(sizeof(*tuninfo) + srhlen); > + memset(tuninfo, 0, sizeof(*tuninfo) + srhlen); > + > + if (encap) > + tuninfo->mode = SEG6_IPTUN_MODE_ENCAP; > + else > + tuninfo->mode = SEG6_IPTUN_MODE_INLINE; > + > + srh = tuninfo->srh; > + srh->hdrlen = (srhlen >> 3) - 1; > + srh->type = 4; > + srh->segments_left = nsegs - 1; > + srh->first_segment = nsegs - 1; > + > + if (cleanup) > + srh->flag_1 |= SR6_FLAG1_CLEANUP; > + if (hmac) > + srh->flag_1 |= SR6_FLAG1_HMAC; > + > + i = srh->first_segment; > + for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) { > + inet_get_addr(s, NULL, &srh->segments[i]); > + i--; > + } > + > + if (hmac) { > + struct sr6_tlv_hmac *tlv; > + > + tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40); > + tlv->tlvhdr.type = SR6_TLV_HMAC; > + tlv->tlvhdr.len = 38; > + tlv->hmackeyid = htonl(hmac); > + } > + > + rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo, > + sizeof(*tuninfo) + srhlen); > + free(tuninfo); > + > + *argcp = argc + 1; > + *argvp = argv - 1; > + > + return 0; > +} > + > static int parse_encap_mpls(struct rtattr *rta, size_t len, > int *argcp, char ***argvp) > { > @@ -573,6 +730,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp) > if (parse_encap_bpf(rta, len, &argc, &argv) < 0) > exit(-1); > break; > + case LWTUNNEL_ENCAP_SEG6: > + parse_encap_seg6(rta, len, &argc, &argv); > + break; > default: > fprintf(stderr, "Error: unsupported encap type\n"); > break; > -- > 2.7.3 > Acked-by: Tom Herbert <tom@herbertland.com> Is there a place do document all the SR functionality? ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2017-01-12 8:35 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-01-10 16:41 [PATCH iproute2 0/3] add support for IPv6 Segment Routing David Lebrun 2017-01-10 16:41 ` [PATCH iproute2 1/3] sr: add header files for SR-IPv6 David Lebrun 2017-01-10 17:25 ` Tom Herbert 2017-01-10 18:33 ` Stephen Hemminger 2017-01-12 8:35 ` David Lebrun 2017-01-10 16:41 ` [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures David Lebrun 2017-01-10 17:25 ` Tom Herbert 2017-01-10 18:35 ` Stephen Hemminger 2017-01-10 16:41 ` [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation David Lebrun 2017-01-10 17:26 ` Tom Herbert
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).