@@ -943,6 +943,7 @@ struct rswitch_ipv4_route {
943
943
u32 ip ;
944
944
u32 subnet ;
945
945
u32 mask ;
946
+ struct fib_nh * nh ;
946
947
struct rswitch_device * dev ;
947
948
struct list_head param_list ;
948
949
struct list_head list ;
@@ -1180,7 +1181,7 @@ static bool rswitch_rx_chain(struct net_device *ndev, int *quota, struct rswitch
1180
1181
skb -> dev = ndev ;
1181
1182
}
1182
1183
1183
- if (learn_chain ) {
1184
+ if (learn_chain && rdev -> priv -> offload_enabled ) {
1184
1185
struct rswitch_private * priv = rdev -> priv ;
1185
1186
struct iphdr * iphdr ;
1186
1187
struct ethhdr * ethhdr ;
@@ -2742,6 +2743,7 @@ static void rswitch_fib_event_add(struct rswitch_fib_event_work *fib_work)
2742
2743
2743
2744
if (!rswitch_add_ipv4_dst_route (new_routing_list , dev , be32_to_cpu (nh -> nh_saddr )))
2744
2745
nh -> fib_nh_flags |= RTNH_F_OFFLOAD ;
2746
+ new_routing_list -> nh = nh ;
2745
2747
}
2746
2748
2747
2749
static void rswitch_fib_event_remove (struct rswitch_fib_event_work * fib_work )
@@ -4123,6 +4125,7 @@ static void cleanup_all_routes(struct rswitch_device *rdev)
4123
4125
mutex_lock (& rdev -> priv -> ipv4_forward_lock );
4124
4126
list_for_each_safe (cur , tmp , & rdev -> routing_list ) {
4125
4127
routing_list = list_entry (cur , struct rswitch_ipv4_route , list );
4128
+ routing_list -> nh -> fib_nh_flags &= ~RTNH_F_OFFLOAD ;
4126
4129
list_for_each_safe (cur_param_list , tmp_param_list , & routing_list -> param_list ) {
4127
4130
param_list =
4128
4131
list_entry (cur_param_list , struct l3_ipv4_fwd_param_list , list );
@@ -4238,6 +4241,47 @@ static struct notifier_block netevent_notifier = {
4238
4241
.notifier_call = rswitch_netevent_cb ,
4239
4242
};
4240
4243
4244
+ static ssize_t l3_offload_show (struct device * dev , struct device_attribute * attr ,
4245
+ char * buf )
4246
+ {
4247
+ return sysfs_emit (buf , "%d\n" , glob_priv -> offload_enabled );
4248
+ }
4249
+
4250
+ static void rswitch_disable_offload (struct rswitch_private * priv )
4251
+ {
4252
+ struct rswitch_device * rdev ;
4253
+
4254
+ read_lock (& priv -> rdev_list_lock );
4255
+ list_for_each_entry (rdev , & priv -> rdev_list , list )
4256
+ cleanup_all_routes (rdev );
4257
+ read_unlock (& priv -> rdev_list_lock );
4258
+ }
4259
+
4260
+ static ssize_t l3_offload_store (struct device * dev , struct device_attribute * attr ,
4261
+ const char * buf , size_t count )
4262
+ {
4263
+ long new_value ;
4264
+
4265
+ if (kstrtol (buf , 10 , & new_value ))
4266
+ return - EINVAL ;
4267
+
4268
+ new_value = !!new_value ;
4269
+ if (new_value != glob_priv -> offload_enabled ) {
4270
+ if (new_value ) {
4271
+ register_fib_notifier (& init_net , & glob_priv -> fib_nb , NULL , NULL );
4272
+ } else {
4273
+ unregister_fib_notifier (& init_net , & glob_priv -> fib_nb );
4274
+ rswitch_disable_offload (glob_priv );
4275
+ }
4276
+
4277
+ glob_priv -> offload_enabled = new_value ;
4278
+ }
4279
+
4280
+ return count ;
4281
+ }
4282
+
4283
+ static DEVICE_ATTR_RW (l3_offload );
4284
+
4241
4285
static int renesas_eth_sw_probe (struct platform_device * pdev )
4242
4286
{
4243
4287
struct rswitch_private * priv ;
@@ -4357,10 +4401,21 @@ static int renesas_eth_sw_probe(struct platform_device *pdev)
4357
4401
ret = register_fib_notifier (& init_net , & priv -> fib_nb , NULL , NULL );
4358
4402
if (ret )
4359
4403
goto unregister_netevent_notifier ;
4404
+
4405
+ priv -> offload_enabled = true;
4406
+ ret = device_create_file (& pdev -> dev , & dev_attr_l3_offload );
4407
+ if (ret ) {
4408
+ dev_err (& priv -> pdev -> dev , "failed to register offload attribute, ret=%d\n" ,
4409
+ ret );
4410
+ goto unregister_fib_notifier ;
4411
+ }
4360
4412
}
4361
4413
4362
4414
return 0 ;
4363
4415
4416
+ unregister_fib_notifier :
4417
+ unregister_fib_notifier (& init_net , & priv -> fib_nb );
4418
+
4364
4419
unregister_netevent_notifier :
4365
4420
unregister_netevent_notifier (& netevent_notifier );
4366
4421
@@ -4389,6 +4444,7 @@ static int renesas_eth_sw_remove(struct platform_device *pdev)
4389
4444
struct rswitch_private * priv = platform_get_drvdata (pdev );
4390
4445
4391
4446
if (!parallel_mode ) {
4447
+ device_remove_file (& pdev -> dev , & dev_attr_l3_offload );
4392
4448
unregister_fib_notifier (& init_net , & priv -> fib_nb );
4393
4449
destroy_workqueue (priv -> rswitch_fib_wq );
4394
4450
unregister_netevent_notifier (& netevent_notifier );
0 commit comments