2828#include <linux/workqueue.h>
2929#include <net/devlink.h>
3030#include <net/ip.h>
31+ #include <net/flow_offload.h>
3132#include <uapi/linux/devlink.h>
3233#include <uapi/linux/ip.h>
3334#include <uapi/linux/udp.h>
@@ -71,6 +72,98 @@ static const struct file_operations nsim_dev_take_snapshot_fops = {
7172 .llseek = generic_file_llseek ,
7273};
7374
75+ static ssize_t nsim_dev_trap_fa_cookie_read (struct file * file ,
76+ char __user * data ,
77+ size_t count , loff_t * ppos )
78+ {
79+ struct nsim_dev * nsim_dev = file -> private_data ;
80+ struct flow_action_cookie * fa_cookie ;
81+ unsigned int buf_len ;
82+ ssize_t ret ;
83+ char * buf ;
84+
85+ spin_lock (& nsim_dev -> fa_cookie_lock );
86+ fa_cookie = nsim_dev -> fa_cookie ;
87+ if (!fa_cookie ) {
88+ ret = - EINVAL ;
89+ goto errout ;
90+ }
91+ buf_len = fa_cookie -> cookie_len * 2 ;
92+ buf = kmalloc (buf_len , GFP_ATOMIC );
93+ if (!buf ) {
94+ ret = - ENOMEM ;
95+ goto errout ;
96+ }
97+ bin2hex (buf , fa_cookie -> cookie , fa_cookie -> cookie_len );
98+ spin_unlock (& nsim_dev -> fa_cookie_lock );
99+
100+ ret = simple_read_from_buffer (data , count , ppos , buf , buf_len );
101+
102+ kfree (buf );
103+ return ret ;
104+
105+ errout :
106+ spin_unlock (& nsim_dev -> fa_cookie_lock );
107+ return ret ;
108+ }
109+
110+ static ssize_t nsim_dev_trap_fa_cookie_write (struct file * file ,
111+ const char __user * data ,
112+ size_t count , loff_t * ppos )
113+ {
114+ struct nsim_dev * nsim_dev = file -> private_data ;
115+ struct flow_action_cookie * fa_cookie ;
116+ size_t cookie_len ;
117+ ssize_t ret ;
118+ char * buf ;
119+
120+ if (* ppos != 0 )
121+ return - EINVAL ;
122+ cookie_len = (count - 1 ) / 2 ;
123+ if ((count - 1 ) % 2 )
124+ return - EINVAL ;
125+ buf = kmalloc (count , GFP_KERNEL | __GFP_NOWARN );
126+ if (!buf )
127+ return - ENOMEM ;
128+
129+ ret = simple_write_to_buffer (buf , count , ppos , data , count );
130+ if (ret < 0 )
131+ goto free_buf ;
132+
133+ fa_cookie = kmalloc (sizeof (* fa_cookie ) + cookie_len ,
134+ GFP_KERNEL | __GFP_NOWARN );
135+ if (!fa_cookie ) {
136+ ret = - ENOMEM ;
137+ goto free_buf ;
138+ }
139+
140+ fa_cookie -> cookie_len = cookie_len ;
141+ ret = hex2bin (fa_cookie -> cookie , buf , cookie_len );
142+ if (ret )
143+ goto free_fa_cookie ;
144+ kfree (buf );
145+
146+ spin_lock (& nsim_dev -> fa_cookie_lock );
147+ kfree (nsim_dev -> fa_cookie );
148+ nsim_dev -> fa_cookie = fa_cookie ;
149+ spin_unlock (& nsim_dev -> fa_cookie_lock );
150+
151+ return count ;
152+
153+ free_fa_cookie :
154+ kfree (fa_cookie );
155+ free_buf :
156+ kfree (buf );
157+ return ret ;
158+ }
159+
160+ static const struct file_operations nsim_dev_trap_fa_cookie_fops = {
161+ .open = simple_open ,
162+ .read = nsim_dev_trap_fa_cookie_read ,
163+ .write = nsim_dev_trap_fa_cookie_write ,
164+ .llseek = generic_file_llseek ,
165+ };
166+
74167static int nsim_dev_debugfs_init (struct nsim_dev * nsim_dev )
75168{
76169 char dev_ddir_name [sizeof (DRV_NAME ) + 10 ];
@@ -97,6 +190,8 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
97190 & nsim_dev -> dont_allow_reload );
98191 debugfs_create_bool ("fail_reload" , 0600 , nsim_dev -> ddir ,
99192 & nsim_dev -> fail_reload );
193+ debugfs_create_file ("trap_flow_action_cookie" , 0600 , nsim_dev -> ddir ,
194+ nsim_dev , & nsim_dev_trap_fa_cookie_fops );
100195 return 0 ;
101196}
102197
@@ -288,6 +383,10 @@ enum {
288383 DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
289384 DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
290385 NSIM_TRAP_METADATA)
386+ #define NSIM_TRAP_DROP_EXT (_id , _group_id , _metadata ) \
387+ DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \
388+ DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
389+ NSIM_TRAP_METADATA | (_metadata))
291390#define NSIM_TRAP_EXCEPTION (_id , _group_id ) \
292391 DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
293392 DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
@@ -309,6 +408,10 @@ static const struct devlink_trap nsim_traps_arr[] = {
309408 NSIM_TRAP_DROP (BLACKHOLE_ROUTE , L3_DROPS ),
310409 NSIM_TRAP_EXCEPTION (TTL_ERROR , L3_DROPS ),
311410 NSIM_TRAP_DROP (TAIL_DROP , BUFFER_DROPS ),
411+ NSIM_TRAP_DROP_EXT (INGRESS_FLOW_ACTION_DROP , ACL_DROPS ,
412+ DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE ),
413+ NSIM_TRAP_DROP_EXT (EGRESS_FLOW_ACTION_DROP , ACL_DROPS ,
414+ DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE ),
312415};
313416
314417#define NSIM_TRAP_L4_DATA_LEN 100
@@ -366,8 +469,13 @@ static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port)
366469
367470 spin_lock (& nsim_trap_data -> trap_lock );
368471 for (i = 0 ; i < ARRAY_SIZE (nsim_traps_arr ); i ++ ) {
472+ struct flow_action_cookie * fa_cookie = NULL ;
369473 struct nsim_trap_item * nsim_trap_item ;
370474 struct sk_buff * skb ;
475+ bool has_fa_cookie ;
476+
477+ has_fa_cookie = nsim_traps_arr [i ].metadata_cap &
478+ DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE ;
371479
372480 nsim_trap_item = & nsim_trap_data -> trap_items_arr [i ];
373481 if (nsim_trap_item -> action == DEVLINK_TRAP_ACTION_DROP )
@@ -383,10 +491,12 @@ static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port)
383491 * softIRQs to prevent lockdep from complaining about
384492 * "incosistent lock state".
385493 */
386- local_bh_disable ();
494+
495+ spin_lock_bh (& nsim_dev -> fa_cookie_lock );
496+ fa_cookie = has_fa_cookie ? nsim_dev -> fa_cookie : NULL ;
387497 devlink_trap_report (devlink , skb , nsim_trap_item -> trap_ctx ,
388- & nsim_dev_port -> devlink_port , NULL );
389- local_bh_enable ( );
498+ & nsim_dev_port -> devlink_port , fa_cookie );
499+ spin_unlock_bh ( & nsim_dev -> fa_cookie_lock );
390500 consume_skb (skb );
391501 }
392502 spin_unlock (& nsim_trap_data -> trap_lock );
@@ -780,6 +890,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
780890 nsim_dev -> fw_update_status = true;
781891 nsim_dev -> max_macs = NSIM_DEV_MAX_MACS_DEFAULT ;
782892 nsim_dev -> test1 = NSIM_DEV_TEST1_DEFAULT ;
893+ spin_lock_init (& nsim_dev -> fa_cookie_lock );
783894
784895 dev_set_drvdata (& nsim_bus_dev -> dev , nsim_dev );
785896
0 commit comments