2323#include <net/flow_dissector.h>
2424#include <net/geneve.h>
2525#include <net/vxlan.h>
26+ #include <net/erspan.h>
2627
2728#include <net/dst.h>
2829#include <net/dst_metadata.h>
@@ -693,6 +694,7 @@ enc_opts_policy[TCA_FLOWER_KEY_ENC_OPTS_MAX + 1] = {
693694 .strict_start_type = TCA_FLOWER_KEY_ENC_OPTS_VXLAN },
694695 [TCA_FLOWER_KEY_ENC_OPTS_GENEVE ] = { .type = NLA_NESTED },
695696 [TCA_FLOWER_KEY_ENC_OPTS_VXLAN ] = { .type = NLA_NESTED },
697+ [TCA_FLOWER_KEY_ENC_OPTS_ERSPAN ] = { .type = NLA_NESTED },
696698};
697699
698700static const struct nla_policy
@@ -708,6 +710,14 @@ vxlan_opt_policy[TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX + 1] = {
708710 [TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP ] = { .type = NLA_U32 },
709711};
710712
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+
711721static void fl_set_key_val (struct nlattr * * tb ,
712722 void * val , int val_type ,
713723 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,
972982 return sizeof (* md );
973983}
974984
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+
9751049static int fl_set_enc_opt (struct nlattr * * tb , struct fl_flow_key * key ,
9761050 struct fl_flow_key * mask ,
9771051 struct netlink_ext_ack * extack )
@@ -1065,6 +1139,39 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
10651139 return - EINVAL ;
10661140 }
10671141
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+
10681175 if (msk_depth )
10691176 nla_opt_msk = nla_next (nla_opt_msk , & msk_depth );
10701177 break ;
@@ -2239,6 +2346,39 @@ static int fl_dump_key_vxlan_opt(struct sk_buff *skb,
22392346 return - EMSGSIZE ;
22402347}
22412348
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+
22422382static int fl_dump_key_ct (struct sk_buff * skb ,
22432383 struct flow_dissector_key_ct * key ,
22442384 struct flow_dissector_key_ct * mask )
@@ -2297,6 +2437,11 @@ static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type,
22972437 if (err )
22982438 goto nla_put_failure ;
22992439 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 ;
23002445 default :
23012446 goto nla_put_failure ;
23022447 }
0 commit comments