Re: [PATCH iproute2-next] tc: f_flower: add geneve option match support to flower

2018-10-02 Thread David Ahern
On 9/28/18 8:03 AM, Simon Horman wrote:
> From: Pieter Jansen van Vuuren 
> 
> Allow matching on options in Geneve tunnel headers.
> 
> The options can be described in the form
> CLASS:TYPE:DATA/CLASS_MASK:TYPE_MASK:DATA_MASK, where CLASS is
> represented as a 16bit hexadecimal value, TYPE as an 8bit
> hexadecimal value and DATA as a variable length hexadecimal value.
> 
> e.g.
>  # ip link add name geneve0 type geneve dstport 0 external
>  # tc qdisc add dev geneve0 ingress
>  # tc filter add dev geneve0 protocol ip parent : \
>  flower \
>enc_src_ip 10.0.99.192 \
>enc_dst_ip 10.0.99.193 \
>enc_key_id 11 \
>geneve_opts 0102:80:1122334421314151/:ff: \
>ip_proto udp \
>action mirred egress redirect dev eth1
> 
> Signed-off-by: Pieter Jansen van Vuuren 
> Signed-off-by: Simon Horman 
> ---
>  man/man8/tc-flower.8 |  13 ++-
>  tc/f_flower.c| 282 
> +++
>  2 files changed, 294 insertions(+), 1 deletion(-)

applied to iproute2-next. Thanks




[PATCH iproute2-next] tc: f_flower: add geneve option match support to flower

2018-09-28 Thread Simon Horman
From: Pieter Jansen van Vuuren 

Allow matching on options in Geneve tunnel headers.

The options can be described in the form
CLASS:TYPE:DATA/CLASS_MASK:TYPE_MASK:DATA_MASK, where CLASS is
represented as a 16bit hexadecimal value, TYPE as an 8bit
hexadecimal value and DATA as a variable length hexadecimal value.

e.g.
 # ip link add name geneve0 type geneve dstport 0 external
 # tc qdisc add dev geneve0 ingress
 # tc filter add dev geneve0 protocol ip parent : \
 flower \
   enc_src_ip 10.0.99.192 \
   enc_dst_ip 10.0.99.193 \
   enc_key_id 11 \
   geneve_opts 0102:80:1122334421314151/:ff: \
   ip_proto udp \
   action mirred egress redirect dev eth1

Signed-off-by: Pieter Jansen van Vuuren 
Signed-off-by: Simon Horman 
---
 man/man8/tc-flower.8 |  13 ++-
 tc/f_flower.c| 282 +++
 2 files changed, 294 insertions(+), 1 deletion(-)

diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
index 305d7efe046a..8be8882592ea 100644
--- a/man/man8/tc-flower.8
+++ b/man/man8/tc-flower.8
@@ -80,6 +80,8 @@ flower \- flow based traffic control filter
 .IR TOS " | "
 .B enc_ttl
 .IR TTL " | "
+.B geneve_opts
+.IR OPTIONS " | "
 .BR ip_flags
 .IR IP_FLAGS
 .SH DESCRIPTION
@@ -283,6 +285,8 @@ bits is assumed.
 .BI enc_tos " NUMBER"
 .TQ
 .BI enc_ttl " NUMBER"
+.TQ
+.BI geneve_opts " OPTIONS"
 Match on IP tunnel metadata. Key id
 .I NUMBER
 is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel).
@@ -295,7 +299,14 @@ is a 16 bit UDP dst port. Tos
 .I NUMBER
 is an 8 bit tos (dscp+ecn) value, ttl
 .I NUMBER
-is an 8 bit time-to-live value.
+is an 8 bit time-to-live value. geneve_opts
+.I OPTIONS
+must be a valid list of comma-separated geneve options where each option
+consists of a key optionally followed by a slash and corresponding mask. If
+the masks is missing, \fBtc\fR assumes a full-length match. The options can
+be described in the form CLASS:TYPE:DATA/CLASS_MASK:TYPE_MASK:DATA_MASK,
+where CLASS is represented as a 16bit hexadecimal value, TYPE as an 8bit
+hexadecimal value and DATA as a variable length hexadecimal value.
 .TP
 .BI ip_flags " IP_FLAGS"
 .I IP_FLAGS
diff --git a/tc/f_flower.c b/tc/f_flower.c
index 59e5f572c542..4a8fb984a35a 100644
--- a/tc/f_flower.c
+++ b/tc/f_flower.c
@@ -79,6 +79,7 @@ static void explain(void)
"   enc_key_id [ KEY-ID ] |\n"
"   enc_tos MASKED-IP_TOS |\n"
"   enc_ttl MASKED-IP_TTL |\n"
+   "   geneve_opts MASKED-OPTIONS |\n"
"   ip_flags IP-FLAGS | \n"
"   enc_dst_port [ port_number ] }\n"
"   FILTERID := X:Y:Z\n"
@@ -589,6 +590,179 @@ static int flower_parse_enc_port(char *str, int type, 
struct nlmsghdr *n)
return 0;
 }
 
+static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n)
+{
+   struct rtattr *nest;
+   char *token;
+   int i, err;
+
+   nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_GENEVE);
+
+   i = 1;
+   token = strsep(, ":");
+   while (token) {
+   switch (i) {
+   case TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS:
+   {
+   __be16 opt_class;
+
+   if (!strlen(token))
+   break;
+   err = get_be16(_class, token, 16);
+   if (err)
+   return err;
+
+   addattr16(n, MAX_MSG, i, opt_class);
+   break;
+   }
+   case TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE:
+   {
+   __u8 opt_type;
+
+   if (!strlen(token))
+   break;
+   err = get_u8(_type, token, 16);
+   if (err)
+   return err;
+
+   addattr8(n, MAX_MSG, i, opt_type);
+   break;
+   }
+   case TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA:
+   {
+   size_t token_len = strlen(token);
+   __u8 *opts;
+
+   if (!token_len)
+   break;
+   opts = malloc(token_len / 2);
+   if (!opts)
+   return -1;
+   if (hex2mem(token, opts, token_len / 2) < 0) {
+   free(opts);
+   return -1;
+   }
+   addattr_l(n, MAX_MSG, i, opts, token_len / 2);
+   free(opts);
+
+   break;
+   }
+   default:
+   fprintf(stderr, "Unknown \"geneve_opts\" type\n");
+