[iproute2,v5] iproute: Set ip/ip6 lwtunnel flags
diff mbox series

Message ID 1546401420-16859-1-git-send-email-wenxu@ucloud.cn
State Accepted
Delegated to: stephen hemminger
Headers show
Series
  • [iproute2,v5] iproute: Set ip/ip6 lwtunnel flags
Related show

Commit Message

wenxu Jan. 2, 2019, 3:57 a.m. UTC
From: wenxu <wenxu@ucloud.cn>

ip l add dev tun type gretap external
ip r a 10.0.0.1 encap ip dst 192.168.152.171 id 1000 dev gretap

For gretap example when the command set the id but don't set the
TUNNEL_KEY flags. There is no key field in the send packet

User can set flags with key, csum, seq
ip r a 10.0.0.1 encap ip dst 192.168.152.171 id 1000 key csum dev gretap

Signed-off-by: wenxu <wenxu@ucloud.cn>
---
 ip/iproute_lwtunnel.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-
 man/man8/ip-route.8.in |  3 ++-
 2 files changed, 59 insertions(+), 2 deletions(-)

Comments

wenxu Jan. 8, 2019, 8:15 a.m. UTC | #1
Hi stephen,


I found the state of this patch is Accepted. I wonder why it didn't merge into the iproute2 master?


BR

wenxu

On 1/2/2019 11:57 AM, wenxu@ucloud.cn wrote:
> From: wenxu <wenxu@ucloud.cn>
>
> ip l add dev tun type gretap external
> ip r a 10.0.0.1 encap ip dst 192.168.152.171 id 1000 dev gretap
>
> For gretap example when the command set the id but don't set the
> TUNNEL_KEY flags. There is no key field in the send packet
>
> User can set flags with key, csum, seq
> ip r a 10.0.0.1 encap ip dst 192.168.152.171 id 1000 key csum dev gretap
>
> Signed-off-by: wenxu <wenxu@ucloud.cn>
> ---
>  ip/iproute_lwtunnel.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  man/man8/ip-route.8.in |  3 ++-
>  2 files changed, 59 insertions(+), 2 deletions(-)
>
> diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
> index aee18ac..03217b8 100644
> --- a/ip/iproute_lwtunnel.c
> +++ b/ip/iproute_lwtunnel.c
> @@ -31,7 +31,7 @@
>  #include <linux/seg6_iptunnel.h>
>  #include <linux/seg6_hmac.h>
>  #include <linux/seg6_local.h>
> -#include <net/if.h>
> +#include <linux/if_tunnel.h>
>  
>  static const char *format_encap_type(int type)
>  {
> @@ -294,6 +294,7 @@ static void print_encap_mpls(FILE *fp, struct rtattr *encap)
>  static void print_encap_ip(FILE *fp, struct rtattr *encap)
>  {
>  	struct rtattr *tb[LWTUNNEL_IP_MAX+1];
> +	__u16 flags;
>  
>  	parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
>  
> @@ -318,6 +319,16 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap)
>  	if (tb[LWTUNNEL_IP_TOS])
>  		print_uint(PRINT_ANY, "tos",
>  			   "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
> +
> +	if (tb[LWTUNNEL_IP_FLAGS]) {
> +		flags = rta_getattr_u16(tb[LWTUNNEL_IP_FLAGS]);
> +		if (flags & TUNNEL_KEY)
> +			print_bool(PRINT_ANY, "key", "key ", true);
> +		if (flags & TUNNEL_CSUM)
> +			print_bool(PRINT_ANY, "csum", "csum ", true);
> +		if (flags & TUNNEL_SEQ)
> +			print_bool(PRINT_ANY, "seq", "seq ", true);
> +	}
>  }
>  
>  static void print_encap_ila(FILE *fp, struct rtattr *encap)
> @@ -354,6 +365,7 @@ static void print_encap_ila(FILE *fp, struct rtattr *encap)
>  static void print_encap_ip6(FILE *fp, struct rtattr *encap)
>  {
>  	struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
> +	__u16 flags;
>  
>  	parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
>  
> @@ -379,6 +391,16 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
>  	if (tb[LWTUNNEL_IP6_TC])
>  		print_uint(PRINT_ANY, "tc",
>  			   "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
> +
> +	if (tb[LWTUNNEL_IP6_FLAGS]) {
> +		flags = rta_getattr_u16(tb[LWTUNNEL_IP6_FLAGS]);
> +		if (flags & TUNNEL_KEY)
> +			print_bool(PRINT_ANY, "key", "key ", true);
> +		if (flags & TUNNEL_CSUM)
> +			print_bool(PRINT_ANY, "csum", "csum ", true);
> +		if (flags & TUNNEL_SEQ)
> +			print_bool(PRINT_ANY, "seq", "seq ", true);
> +	}
>  }
>  
>  static void print_encap_bpf(FILE *fp, struct rtattr *encap)
> @@ -777,9 +799,11 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
>  			  int *argcp, char ***argvp)
>  {
>  	int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
> +	int key_ok = 0, csum_ok = 0, seq_ok = 0;
>  	char **argv = *argvp;
>  	int argc = *argcp;
>  	int ret = 0;
> +	__u16 flags = 0;
>  
>  	while (argc > 0) {
>  		if (strcmp(*argv, "id") == 0) {
> @@ -827,6 +851,18 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
>  			if (get_u8(&ttl, *argv, 0))
>  				invarg("\"ttl\" value is invalid\n", *argv);
>  			ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
> +		} else if (strcmp(*argv, "key") == 0) {
> +			if (key_ok++)
> +				duparg2("key", *argv);
> +			flags |= TUNNEL_KEY;
> +		} else if (strcmp(*argv, "csum") == 0) {
> +			if (csum_ok++)
> +				duparg2("csum", *argv);
> +			flags |= TUNNEL_CSUM;
> +		} else if (strcmp(*argv, "seq") == 0) {
> +			if (seq_ok++)
> +				duparg2("seq", *argv);
> +			flags |= TUNNEL_SEQ;
>  		} else {
>  			break;
>  		}
> @@ -835,6 +871,9 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
>  		argc--; argv++;
>  	}
>  
> +	if (flags)
> +		ret = rta_addattr16(rta, len,  LWTUNNEL_IP_FLAGS, flags);
> +
>  	/* argv is currently the first unparsed argument,
>  	 * but the lwt_parse_encap() caller will move to the next,
>  	 * so step back
> @@ -927,9 +966,11 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
>  			   int *argcp, char ***argvp)
>  {
>  	int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
> +	int key_ok = 0, csum_ok = 0, seq_ok = 0;
>  	char **argv = *argvp;
>  	int argc = *argcp;
>  	int ret = 0;
> +	__u16 flags = 0;
>  
>  	while (argc > 0) {
>  		if (strcmp(*argv, "id") == 0) {
> @@ -979,6 +1020,18 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
>  				       *argv);
>  			ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
>  					   hoplimit);
> +		} else if (strcmp(*argv, "key") == 0) {
> +			if (key_ok++)
> +				duparg2("key", *argv);
> +			flags |= TUNNEL_KEY;
> +		} else if (strcmp(*argv, "csum") == 0) {
> +			if (csum_ok++)
> +				duparg2("csum", *argv);
> +			flags |= TUNNEL_CSUM;
> +		} else if (strcmp(*argv, "seq") == 0) {
> +			if (seq_ok++)
> +				duparg2("seq", *argv);
> +			flags |= TUNNEL_SEQ;
>  		} else {
>  			break;
>  		}
> @@ -987,6 +1040,9 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
>  		argc--; argv++;
>  	}
>  
> +	if (flags)
> +		ret = rta_addattr16(rta, len,  LWTUNNEL_IP6_FLAGS, flags);
> +
>  	/* argv is currently the first unparsed argument,
>  	 * but the lwt_parse_encap() caller will move to the next,
>  	 * so step back
> diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
> index 26dfe0b..1ab9b1c 100644
> --- a/man/man8/ip-route.8.in
> +++ b/man/man8/ip-route.8.in
> @@ -737,7 +737,8 @@ is a set of encapsulation attributes specific to the
>  .B tos
>  .IR TOS " ] ["
>  .B  ttl
> -.IR TTL " ]"
> +.IR TTL " ] [ "
> +.BR key " ] [" csum " ] [ " seq " ] "
>  .in -2
>  .sp
>
wenxu Jan. 22, 2019, 6:14 a.m. UTC | #2
Hi stephen & David,

The status of this patch shows "Accepted' for long time.

http://patchwork.ozlabs.org/patch/1019880/

But it doesn't applied to master. There are some other problem for this patch?


BR

wenxu

On 1/2/2019 11:57 AM, wenxu@ucloud.cn wrote:
> From: wenxu <wenxu@ucloud.cn>
>
> ip l add dev tun type gretap external
> ip r a 10.0.0.1 encap ip dst 192.168.152.171 id 1000 dev gretap
>
> For gretap example when the command set the id but don't set the
> TUNNEL_KEY flags. There is no key field in the send packet
>
> User can set flags with key, csum, seq
> ip r a 10.0.0.1 encap ip dst 192.168.152.171 id 1000 key csum dev gretap
>
> Signed-off-by: wenxu <wenxu@ucloud.cn>
> ---
>  ip/iproute_lwtunnel.c  | 58 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  man/man8/ip-route.8.in |  3 ++-
>  2 files changed, 59 insertions(+), 2 deletions(-)
>
> diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
> index aee18ac..03217b8 100644
> --- a/ip/iproute_lwtunnel.c
> +++ b/ip/iproute_lwtunnel.c
> @@ -31,7 +31,7 @@
>  #include <linux/seg6_iptunnel.h>
>  #include <linux/seg6_hmac.h>
>  #include <linux/seg6_local.h>
> -#include <net/if.h>
> +#include <linux/if_tunnel.h>
>  
>  static const char *format_encap_type(int type)
>  {
> @@ -294,6 +294,7 @@ static void print_encap_mpls(FILE *fp, struct rtattr *encap)
>  static void print_encap_ip(FILE *fp, struct rtattr *encap)
>  {
>  	struct rtattr *tb[LWTUNNEL_IP_MAX+1];
> +	__u16 flags;
>  
>  	parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
>  
> @@ -318,6 +319,16 @@ static void print_encap_ip(FILE *fp, struct rtattr *encap)
>  	if (tb[LWTUNNEL_IP_TOS])
>  		print_uint(PRINT_ANY, "tos",
>  			   "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
> +
> +	if (tb[LWTUNNEL_IP_FLAGS]) {
> +		flags = rta_getattr_u16(tb[LWTUNNEL_IP_FLAGS]);
> +		if (flags & TUNNEL_KEY)
> +			print_bool(PRINT_ANY, "key", "key ", true);
> +		if (flags & TUNNEL_CSUM)
> +			print_bool(PRINT_ANY, "csum", "csum ", true);
> +		if (flags & TUNNEL_SEQ)
> +			print_bool(PRINT_ANY, "seq", "seq ", true);
> +	}
>  }
>  
>  static void print_encap_ila(FILE *fp, struct rtattr *encap)
> @@ -354,6 +365,7 @@ static void print_encap_ila(FILE *fp, struct rtattr *encap)
>  static void print_encap_ip6(FILE *fp, struct rtattr *encap)
>  {
>  	struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
> +	__u16 flags;
>  
>  	parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
>  
> @@ -379,6 +391,16 @@ static void print_encap_ip6(FILE *fp, struct rtattr *encap)
>  	if (tb[LWTUNNEL_IP6_TC])
>  		print_uint(PRINT_ANY, "tc",
>  			   "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
> +
> +	if (tb[LWTUNNEL_IP6_FLAGS]) {
> +		flags = rta_getattr_u16(tb[LWTUNNEL_IP6_FLAGS]);
> +		if (flags & TUNNEL_KEY)
> +			print_bool(PRINT_ANY, "key", "key ", true);
> +		if (flags & TUNNEL_CSUM)
> +			print_bool(PRINT_ANY, "csum", "csum ", true);
> +		if (flags & TUNNEL_SEQ)
> +			print_bool(PRINT_ANY, "seq", "seq ", true);
> +	}
>  }
>  
>  static void print_encap_bpf(FILE *fp, struct rtattr *encap)
> @@ -777,9 +799,11 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
>  			  int *argcp, char ***argvp)
>  {
>  	int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
> +	int key_ok = 0, csum_ok = 0, seq_ok = 0;
>  	char **argv = *argvp;
>  	int argc = *argcp;
>  	int ret = 0;
> +	__u16 flags = 0;
>  
>  	while (argc > 0) {
>  		if (strcmp(*argv, "id") == 0) {
> @@ -827,6 +851,18 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
>  			if (get_u8(&ttl, *argv, 0))
>  				invarg("\"ttl\" value is invalid\n", *argv);
>  			ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
> +		} else if (strcmp(*argv, "key") == 0) {
> +			if (key_ok++)
> +				duparg2("key", *argv);
> +			flags |= TUNNEL_KEY;
> +		} else if (strcmp(*argv, "csum") == 0) {
> +			if (csum_ok++)
> +				duparg2("csum", *argv);
> +			flags |= TUNNEL_CSUM;
> +		} else if (strcmp(*argv, "seq") == 0) {
> +			if (seq_ok++)
> +				duparg2("seq", *argv);
> +			flags |= TUNNEL_SEQ;
>  		} else {
>  			break;
>  		}
> @@ -835,6 +871,9 @@ static int parse_encap_ip(struct rtattr *rta, size_t len,
>  		argc--; argv++;
>  	}
>  
> +	if (flags)
> +		ret = rta_addattr16(rta, len,  LWTUNNEL_IP_FLAGS, flags);
> +
>  	/* argv is currently the first unparsed argument,
>  	 * but the lwt_parse_encap() caller will move to the next,
>  	 * so step back
> @@ -927,9 +966,11 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
>  			   int *argcp, char ***argvp)
>  {
>  	int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
> +	int key_ok = 0, csum_ok = 0, seq_ok = 0;
>  	char **argv = *argvp;
>  	int argc = *argcp;
>  	int ret = 0;
> +	__u16 flags = 0;
>  
>  	while (argc > 0) {
>  		if (strcmp(*argv, "id") == 0) {
> @@ -979,6 +1020,18 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
>  				       *argv);
>  			ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
>  					   hoplimit);
> +		} else if (strcmp(*argv, "key") == 0) {
> +			if (key_ok++)
> +				duparg2("key", *argv);
> +			flags |= TUNNEL_KEY;
> +		} else if (strcmp(*argv, "csum") == 0) {
> +			if (csum_ok++)
> +				duparg2("csum", *argv);
> +			flags |= TUNNEL_CSUM;
> +		} else if (strcmp(*argv, "seq") == 0) {
> +			if (seq_ok++)
> +				duparg2("seq", *argv);
> +			flags |= TUNNEL_SEQ;
>  		} else {
>  			break;
>  		}
> @@ -987,6 +1040,9 @@ static int parse_encap_ip6(struct rtattr *rta, size_t len,
>  		argc--; argv++;
>  	}
>  
> +	if (flags)
> +		ret = rta_addattr16(rta, len,  LWTUNNEL_IP6_FLAGS, flags);
> +
>  	/* argv is currently the first unparsed argument,
>  	 * but the lwt_parse_encap() caller will move to the next,
>  	 * so step back
> diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
> index 26dfe0b..1ab9b1c 100644
> --- a/man/man8/ip-route.8.in
> +++ b/man/man8/ip-route.8.in
> @@ -737,7 +737,8 @@ is a set of encapsulation attributes specific to the
>  .B tos
>  .IR TOS " ] ["
>  .B  ttl
> -.IR TTL " ]"
> +.IR TTL " ] [ "
> +.BR key " ] [" csum " ] [ " seq " ] "
>  .in -2
>  .sp
>

Patch
diff mbox series

diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index aee18ac..03217b8 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -31,7 +31,7 @@ 
 #include <linux/seg6_iptunnel.h>
 #include <linux/seg6_hmac.h>
 #include <linux/seg6_local.h>
-#include <net/if.h>
+#include <linux/if_tunnel.h>
 
 static const char *format_encap_type(int type)
 {
@@ -294,6 +294,7 @@  static void print_encap_mpls(FILE *fp, struct rtattr *encap)
 static void print_encap_ip(FILE *fp, struct rtattr *encap)
 {
 	struct rtattr *tb[LWTUNNEL_IP_MAX+1];
+	__u16 flags;
 
 	parse_rtattr_nested(tb, LWTUNNEL_IP_MAX, encap);
 
@@ -318,6 +319,16 @@  static void print_encap_ip(FILE *fp, struct rtattr *encap)
 	if (tb[LWTUNNEL_IP_TOS])
 		print_uint(PRINT_ANY, "tos",
 			   "tos %d ", rta_getattr_u8(tb[LWTUNNEL_IP_TOS]));
+
+	if (tb[LWTUNNEL_IP_FLAGS]) {
+		flags = rta_getattr_u16(tb[LWTUNNEL_IP_FLAGS]);
+		if (flags & TUNNEL_KEY)
+			print_bool(PRINT_ANY, "key", "key ", true);
+		if (flags & TUNNEL_CSUM)
+			print_bool(PRINT_ANY, "csum", "csum ", true);
+		if (flags & TUNNEL_SEQ)
+			print_bool(PRINT_ANY, "seq", "seq ", true);
+	}
 }
 
 static void print_encap_ila(FILE *fp, struct rtattr *encap)
@@ -354,6 +365,7 @@  static void print_encap_ila(FILE *fp, struct rtattr *encap)
 static void print_encap_ip6(FILE *fp, struct rtattr *encap)
 {
 	struct rtattr *tb[LWTUNNEL_IP6_MAX+1];
+	__u16 flags;
 
 	parse_rtattr_nested(tb, LWTUNNEL_IP6_MAX, encap);
 
@@ -379,6 +391,16 @@  static void print_encap_ip6(FILE *fp, struct rtattr *encap)
 	if (tb[LWTUNNEL_IP6_TC])
 		print_uint(PRINT_ANY, "tc",
 			   "tc %u ", rta_getattr_u8(tb[LWTUNNEL_IP6_TC]));
+
+	if (tb[LWTUNNEL_IP6_FLAGS]) {
+		flags = rta_getattr_u16(tb[LWTUNNEL_IP6_FLAGS]);
+		if (flags & TUNNEL_KEY)
+			print_bool(PRINT_ANY, "key", "key ", true);
+		if (flags & TUNNEL_CSUM)
+			print_bool(PRINT_ANY, "csum", "csum ", true);
+		if (flags & TUNNEL_SEQ)
+			print_bool(PRINT_ANY, "seq", "seq ", true);
+	}
 }
 
 static void print_encap_bpf(FILE *fp, struct rtattr *encap)
@@ -777,9 +799,11 @@  static int parse_encap_ip(struct rtattr *rta, size_t len,
 			  int *argcp, char ***argvp)
 {
 	int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
+	int key_ok = 0, csum_ok = 0, seq_ok = 0;
 	char **argv = *argvp;
 	int argc = *argcp;
 	int ret = 0;
+	__u16 flags = 0;
 
 	while (argc > 0) {
 		if (strcmp(*argv, "id") == 0) {
@@ -827,6 +851,18 @@  static int parse_encap_ip(struct rtattr *rta, size_t len,
 			if (get_u8(&ttl, *argv, 0))
 				invarg("\"ttl\" value is invalid\n", *argv);
 			ret = rta_addattr8(rta, len, LWTUNNEL_IP_TTL, ttl);
+		} else if (strcmp(*argv, "key") == 0) {
+			if (key_ok++)
+				duparg2("key", *argv);
+			flags |= TUNNEL_KEY;
+		} else if (strcmp(*argv, "csum") == 0) {
+			if (csum_ok++)
+				duparg2("csum", *argv);
+			flags |= TUNNEL_CSUM;
+		} else if (strcmp(*argv, "seq") == 0) {
+			if (seq_ok++)
+				duparg2("seq", *argv);
+			flags |= TUNNEL_SEQ;
 		} else {
 			break;
 		}
@@ -835,6 +871,9 @@  static int parse_encap_ip(struct rtattr *rta, size_t len,
 		argc--; argv++;
 	}
 
+	if (flags)
+		ret = rta_addattr16(rta, len,  LWTUNNEL_IP_FLAGS, flags);
+
 	/* argv is currently the first unparsed argument,
 	 * but the lwt_parse_encap() caller will move to the next,
 	 * so step back
@@ -927,9 +966,11 @@  static int parse_encap_ip6(struct rtattr *rta, size_t len,
 			   int *argcp, char ***argvp)
 {
 	int id_ok = 0, dst_ok = 0, src_ok = 0, tos_ok = 0, ttl_ok = 0;
+	int key_ok = 0, csum_ok = 0, seq_ok = 0;
 	char **argv = *argvp;
 	int argc = *argcp;
 	int ret = 0;
+	__u16 flags = 0;
 
 	while (argc > 0) {
 		if (strcmp(*argv, "id") == 0) {
@@ -979,6 +1020,18 @@  static int parse_encap_ip6(struct rtattr *rta, size_t len,
 				       *argv);
 			ret = rta_addattr8(rta, len, LWTUNNEL_IP6_HOPLIMIT,
 					   hoplimit);
+		} else if (strcmp(*argv, "key") == 0) {
+			if (key_ok++)
+				duparg2("key", *argv);
+			flags |= TUNNEL_KEY;
+		} else if (strcmp(*argv, "csum") == 0) {
+			if (csum_ok++)
+				duparg2("csum", *argv);
+			flags |= TUNNEL_CSUM;
+		} else if (strcmp(*argv, "seq") == 0) {
+			if (seq_ok++)
+				duparg2("seq", *argv);
+			flags |= TUNNEL_SEQ;
 		} else {
 			break;
 		}
@@ -987,6 +1040,9 @@  static int parse_encap_ip6(struct rtattr *rta, size_t len,
 		argc--; argv++;
 	}
 
+	if (flags)
+		ret = rta_addattr16(rta, len,  LWTUNNEL_IP6_FLAGS, flags);
+
 	/* argv is currently the first unparsed argument,
 	 * but the lwt_parse_encap() caller will move to the next,
 	 * so step back
diff --git a/man/man8/ip-route.8.in b/man/man8/ip-route.8.in
index 26dfe0b..1ab9b1c 100644
--- a/man/man8/ip-route.8.in
+++ b/man/man8/ip-route.8.in
@@ -737,7 +737,8 @@  is a set of encapsulation attributes specific to the
 .B tos
 .IR TOS " ] ["
 .B  ttl
-.IR TTL " ]"
+.IR TTL " ] [ "
+.BR key " ] [" csum " ] [ " seq " ] "
 .in -2
 .sp