1111#include <linux/rtnetlink.h>
1212#include <net/geneve.h>
1313#include <net/vxlan.h>
14+ #include <net/erspan.h>
1415#include <net/netlink.h>
1516#include <net/pkt_sched.h>
1617#include <net/dst.h>
@@ -58,6 +59,7 @@ enc_opts_policy[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1] = {
5859 .strict_start_type = TCA_TUNNEL_KEY_ENC_OPTS_VXLAN },
5960 [TCA_TUNNEL_KEY_ENC_OPTS_GENEVE ] = { .type = NLA_NESTED },
6061 [TCA_TUNNEL_KEY_ENC_OPTS_VXLAN ] = { .type = NLA_NESTED },
62+ [TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN ] = { .type = NLA_NESTED },
6163};
6264
6365static const struct nla_policy
@@ -73,6 +75,14 @@ vxlan_opt_policy[TCA_TUNNEL_KEY_ENC_OPT_VXLAN_MAX + 1] = {
7375 [TCA_TUNNEL_KEY_ENC_OPT_VXLAN_GBP ] = { .type = NLA_U32 },
7476};
7577
78+ static const struct nla_policy
79+ erspan_opt_policy [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1 ] = {
80+ [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER ] = { .type = NLA_U8 },
81+ [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX ] = { .type = NLA_U32 },
82+ [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR ] = { .type = NLA_U8 },
83+ [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID ] = { .type = NLA_U8 },
84+ };
85+
7686static int
7787tunnel_key_copy_geneve_opt (const struct nlattr * nla , void * dst , int dst_len ,
7888 struct netlink_ext_ack * extack )
@@ -151,6 +161,59 @@ tunnel_key_copy_vxlan_opt(const struct nlattr *nla, void *dst, int dst_len,
151161 return sizeof (struct vxlan_metadata );
152162}
153163
164+ static int
165+ tunnel_key_copy_erspan_opt (const struct nlattr * nla , void * dst , int dst_len ,
166+ struct netlink_ext_ack * extack )
167+ {
168+ struct nlattr * tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX + 1 ];
169+ int err ;
170+ u8 ver ;
171+
172+ err = nla_parse_nested (tb , TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_MAX , nla ,
173+ erspan_opt_policy , extack );
174+ if (err < 0 )
175+ return err ;
176+
177+ if (!tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER ]) {
178+ NL_SET_ERR_MSG (extack , "Missing tunnel key erspan option ver" );
179+ return - EINVAL ;
180+ }
181+
182+ ver = nla_get_u8 (tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER ]);
183+ if (ver == 1 ) {
184+ if (!tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX ]) {
185+ NL_SET_ERR_MSG (extack , "Missing tunnel key erspan option index" );
186+ return - EINVAL ;
187+ }
188+ } else if (ver == 2 ) {
189+ if (!tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR ] ||
190+ !tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID ]) {
191+ NL_SET_ERR_MSG (extack , "Missing tunnel key erspan option dir or hwid" );
192+ return - EINVAL ;
193+ }
194+ } else {
195+ NL_SET_ERR_MSG (extack , "Tunnel key erspan option ver is incorrect" );
196+ return - EINVAL ;
197+ }
198+
199+ if (dst ) {
200+ struct erspan_metadata * md = dst ;
201+
202+ md -> version = ver ;
203+ if (ver == 1 ) {
204+ nla = tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX ];
205+ md -> u .index = nla_get_be32 (nla );
206+ } else {
207+ nla = tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR ];
208+ md -> u .md2 .dir = nla_get_u8 (nla );
209+ nla = tb [TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID ];
210+ set_hwid (& md -> u .md2 , nla_get_u8 (nla ));
211+ }
212+ }
213+
214+ return sizeof (struct erspan_metadata );
215+ }
216+
154217static int tunnel_key_copy_opts (const struct nlattr * nla , u8 * dst ,
155218 int dst_len , struct netlink_ext_ack * extack )
156219{
@@ -192,6 +255,18 @@ static int tunnel_key_copy_opts(const struct nlattr *nla, u8 *dst,
192255 opts_len += opt_len ;
193256 type = TUNNEL_VXLAN_OPT ;
194257 break ;
258+ case TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN :
259+ if (type ) {
260+ NL_SET_ERR_MSG (extack , "Duplicate type for erspan options" );
261+ return - EINVAL ;
262+ }
263+ opt_len = tunnel_key_copy_erspan_opt (attr , dst ,
264+ dst_len , extack );
265+ if (opt_len < 0 )
266+ return opt_len ;
267+ opts_len += opt_len ;
268+ type = TUNNEL_ERSPAN_OPT ;
269+ break ;
195270 }
196271 }
197272
@@ -234,6 +309,14 @@ static int tunnel_key_opts_set(struct nlattr *nla, struct ip_tunnel_info *info,
234309 opts_len , extack );
235310#else
236311 return - EAFNOSUPPORT ;
312+ #endif
313+ case TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN :
314+ #if IS_ENABLED (CONFIG_INET )
315+ info -> key .tun_flags |= TUNNEL_ERSPAN_OPT ;
316+ return tunnel_key_copy_opts (nla , ip_tunnel_info_opts (info ),
317+ opts_len , extack );
318+ #else
319+ return - EAFNOSUPPORT ;
237320#endif
238321 default :
239322 NL_SET_ERR_MSG (extack , "Cannot set tunnel options for unknown tunnel type" );
@@ -530,6 +613,37 @@ static int tunnel_key_vxlan_opts_dump(struct sk_buff *skb,
530613 return 0 ;
531614}
532615
616+ static int tunnel_key_erspan_opts_dump (struct sk_buff * skb ,
617+ const struct ip_tunnel_info * info )
618+ {
619+ struct erspan_metadata * md = (struct erspan_metadata * )(info + 1 );
620+ struct nlattr * start ;
621+
622+ start = nla_nest_start_noflag (skb , TCA_TUNNEL_KEY_ENC_OPTS_ERSPAN );
623+ if (!start )
624+ return - EMSGSIZE ;
625+
626+ if (nla_put_u8 (skb , TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_VER , md -> version ))
627+ goto err ;
628+
629+ if (md -> version == 1 &&
630+ nla_put_be32 (skb , TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_INDEX , md -> u .index ))
631+ goto err ;
632+
633+ if (md -> version == 2 &&
634+ (nla_put_u8 (skb , TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_DIR ,
635+ md -> u .md2 .dir ) ||
636+ nla_put_u8 (skb , TCA_TUNNEL_KEY_ENC_OPT_ERSPAN_HWID ,
637+ get_hwid (& md -> u .md2 ))))
638+ goto err ;
639+
640+ nla_nest_end (skb , start );
641+ return 0 ;
642+ err :
643+ nla_nest_cancel (skb , start );
644+ return - EMSGSIZE ;
645+ }
646+
533647static int tunnel_key_opts_dump (struct sk_buff * skb ,
534648 const struct ip_tunnel_info * info )
535649{
@@ -551,6 +665,10 @@ static int tunnel_key_opts_dump(struct sk_buff *skb,
551665 err = tunnel_key_vxlan_opts_dump (skb , info );
552666 if (err )
553667 goto err_out ;
668+ } else if (info -> key .tun_flags & TUNNEL_ERSPAN_OPT ) {
669+ err = tunnel_key_erspan_opts_dump (skb , info );
670+ if (err )
671+ goto err_out ;
554672 } else {
555673err_out :
556674 nla_nest_cancel (skb , start );
0 commit comments