* [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
* [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
* [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 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 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 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
* 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 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
* 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
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).