23
23
#include <net/flow_dissector.h>
24
24
#include <net/geneve.h>
25
25
#include <net/vxlan.h>
26
+ #include <net/erspan.h>
26
27
27
28
#include <net/dst.h>
28
29
#include <net/dst_metadata.h>
@@ -693,6 +694,7 @@ enc_opts_policy[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1] = {
693
694
.strict_start_type = TCA_FLOWER_KEY_ENC_OPTS_VXLAN },
694
695
[TCA_FLOWER_KEY_ENC_OPTS_GENEVE ] = { .type = NLA_NESTED },
695
696
[TCA_FLOWER_KEY_ENC_OPTS_VXLAN ] = { .type = NLA_NESTED },
697
+ [TCA_FLOWER_KEY_ENC_OPTS_ERSPAN ] = { .type = NLA_NESTED },
696
698
};
697
699
698
700
static const struct nla_policy
@@ -708,6 +710,14 @@ vxlan_opt_policy[TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX + 1] = {
708
710
[TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP ] = { .type = NLA_U32 },
709
711
};
710
712
713
+ static const struct nla_policy
714
+ erspan_opt_policy [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX + 1 ] = {
715
+ [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER ] = { .type = NLA_U8 },
716
+ [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX ] = { .type = NLA_U32 },
717
+ [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR ] = { .type = NLA_U8 },
718
+ [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID ] = { .type = NLA_U8 },
719
+ };
720
+
711
721
static void fl_set_key_val (struct nlattr * * tb ,
712
722
void * val , int val_type ,
713
723
void * mask , int mask_type , int len )
@@ -972,6 +982,70 @@ static int fl_set_vxlan_opt(const struct nlattr *nla, struct fl_flow_key *key,
972
982
return sizeof (* md );
973
983
}
974
984
985
+ static int fl_set_erspan_opt (const struct nlattr * nla , struct fl_flow_key * key ,
986
+ int depth , int option_len ,
987
+ struct netlink_ext_ack * extack )
988
+ {
989
+ struct nlattr * tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX + 1 ];
990
+ struct erspan_metadata * md ;
991
+ int err ;
992
+
993
+ md = (struct erspan_metadata * )& key -> enc_opts .data [key -> enc_opts .len ];
994
+ memset (md , 0xff , sizeof (* md ));
995
+ md -> version = 1 ;
996
+
997
+ if (!depth )
998
+ return sizeof (* md );
999
+
1000
+ if (nla_type (nla ) != TCA_FLOWER_KEY_ENC_OPTS_ERSPAN ) {
1001
+ NL_SET_ERR_MSG (extack , "Non-erspan option type for mask" );
1002
+ return - EINVAL ;
1003
+ }
1004
+
1005
+ err = nla_parse_nested (tb , TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX , nla ,
1006
+ erspan_opt_policy , extack );
1007
+ if (err < 0 )
1008
+ return err ;
1009
+
1010
+ if (!option_len && !tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER ]) {
1011
+ NL_SET_ERR_MSG (extack , "Missing tunnel key erspan option ver" );
1012
+ return - EINVAL ;
1013
+ }
1014
+
1015
+ if (tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER ])
1016
+ md -> version = nla_get_u8 (tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER ]);
1017
+
1018
+ if (md -> version == 1 ) {
1019
+ if (!option_len && !tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX ]) {
1020
+ NL_SET_ERR_MSG (extack , "Missing tunnel key erspan option index" );
1021
+ return - EINVAL ;
1022
+ }
1023
+ if (tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX ]) {
1024
+ nla = tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX ];
1025
+ md -> u .index = nla_get_be32 (nla );
1026
+ }
1027
+ } else if (md -> version == 2 ) {
1028
+ if (!option_len && (!tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR ] ||
1029
+ !tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID ])) {
1030
+ NL_SET_ERR_MSG (extack , "Missing tunnel key erspan option dir or hwid" );
1031
+ return - EINVAL ;
1032
+ }
1033
+ if (tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR ]) {
1034
+ nla = tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR ];
1035
+ md -> u .md2 .dir = nla_get_u8 (nla );
1036
+ }
1037
+ if (tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID ]) {
1038
+ nla = tb [TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID ];
1039
+ set_hwid (& md -> u .md2 , nla_get_u8 (nla ));
1040
+ }
1041
+ } else {
1042
+ NL_SET_ERR_MSG (extack , "Tunnel key erspan option ver is incorrect" );
1043
+ return - EINVAL ;
1044
+ }
1045
+
1046
+ return sizeof (* md );
1047
+ }
1048
+
975
1049
static int fl_set_enc_opt (struct nlattr * * tb , struct fl_flow_key * key ,
976
1050
struct fl_flow_key * mask ,
977
1051
struct netlink_ext_ack * extack )
@@ -1065,6 +1139,39 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
1065
1139
return - EINVAL ;
1066
1140
}
1067
1141
1142
+ if (msk_depth )
1143
+ nla_opt_msk = nla_next (nla_opt_msk , & msk_depth );
1144
+ break ;
1145
+ case TCA_FLOWER_KEY_ENC_OPTS_ERSPAN :
1146
+ if (key -> enc_opts .dst_opt_type ) {
1147
+ NL_SET_ERR_MSG (extack , "Duplicate type for erspan options" );
1148
+ return - EINVAL ;
1149
+ }
1150
+ option_len = 0 ;
1151
+ key -> enc_opts .dst_opt_type = TUNNEL_ERSPAN_OPT ;
1152
+ option_len = fl_set_erspan_opt (nla_opt_key , key ,
1153
+ key_depth , option_len ,
1154
+ extack );
1155
+ if (option_len < 0 )
1156
+ return option_len ;
1157
+
1158
+ key -> enc_opts .len += option_len ;
1159
+ /* At the same time we need to parse through the mask
1160
+ * in order to verify exact and mask attribute lengths.
1161
+ */
1162
+ mask -> enc_opts .dst_opt_type = TUNNEL_ERSPAN_OPT ;
1163
+ option_len = fl_set_erspan_opt (nla_opt_msk , mask ,
1164
+ msk_depth , option_len ,
1165
+ extack );
1166
+ if (option_len < 0 )
1167
+ return option_len ;
1168
+
1169
+ mask -> enc_opts .len += option_len ;
1170
+ if (key -> enc_opts .len != mask -> enc_opts .len ) {
1171
+ NL_SET_ERR_MSG (extack , "Key and mask miss aligned" );
1172
+ return - EINVAL ;
1173
+ }
1174
+
1068
1175
if (msk_depth )
1069
1176
nla_opt_msk = nla_next (nla_opt_msk , & msk_depth );
1070
1177
break ;
@@ -2239,6 +2346,39 @@ static int fl_dump_key_vxlan_opt(struct sk_buff *skb,
2239
2346
return - EMSGSIZE ;
2240
2347
}
2241
2348
2349
+ static int fl_dump_key_erspan_opt (struct sk_buff * skb ,
2350
+ struct flow_dissector_key_enc_opts * enc_opts )
2351
+ {
2352
+ struct erspan_metadata * md ;
2353
+ struct nlattr * nest ;
2354
+
2355
+ nest = nla_nest_start_noflag (skb , TCA_FLOWER_KEY_ENC_OPTS_ERSPAN );
2356
+ if (!nest )
2357
+ goto nla_put_failure ;
2358
+
2359
+ md = (struct erspan_metadata * )& enc_opts -> data [0 ];
2360
+ if (nla_put_u8 (skb , TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER , md -> version ))
2361
+ goto nla_put_failure ;
2362
+
2363
+ if (md -> version == 1 &&
2364
+ nla_put_be32 (skb , TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX , md -> u .index ))
2365
+ goto nla_put_failure ;
2366
+
2367
+ if (md -> version == 2 &&
2368
+ (nla_put_u8 (skb , TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR ,
2369
+ md -> u .md2 .dir ) ||
2370
+ nla_put_u8 (skb , TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID ,
2371
+ get_hwid (& md -> u .md2 ))))
2372
+ goto nla_put_failure ;
2373
+
2374
+ nla_nest_end (skb , nest );
2375
+ return 0 ;
2376
+
2377
+ nla_put_failure :
2378
+ nla_nest_cancel (skb , nest );
2379
+ return - EMSGSIZE ;
2380
+ }
2381
+
2242
2382
static int fl_dump_key_ct (struct sk_buff * skb ,
2243
2383
struct flow_dissector_key_ct * key ,
2244
2384
struct flow_dissector_key_ct * mask )
@@ -2297,6 +2437,11 @@ static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type,
2297
2437
if (err )
2298
2438
goto nla_put_failure ;
2299
2439
break ;
2440
+ case TUNNEL_ERSPAN_OPT :
2441
+ err = fl_dump_key_erspan_opt (skb , enc_opts );
2442
+ if (err )
2443
+ goto nla_put_failure ;
2444
+ break ;
2300
2445
default :
2301
2446
goto nla_put_failure ;
2302
2447
}
0 commit comments