7
7
#include <net/inet_dscp.h>
8
8
#include <net/switchdev.h>
9
9
#include <linux/rhashtable.h>
10
+ #include <net/nexthop.h>
10
11
11
12
#include "prestera.h"
12
13
#include "prestera_router_hw.h"
@@ -26,9 +27,10 @@ struct prestera_kern_fib_cache {
26
27
} lpm_info ; /* hold prepared lpm info */
27
28
/* Indicate if route is not overlapped by another table */
28
29
struct rhash_head ht_node ; /* node of prestera_router */
29
- struct fib_info * fi ;
30
- dscp_t kern_dscp ;
31
- u8 kern_type ;
30
+ union {
31
+ struct fib_notifier_info info ; /* point to any of 4/6 */
32
+ struct fib_entry_notifier_info fen4_info ;
33
+ };
32
34
bool reachable ;
33
35
};
34
36
@@ -51,15 +53,41 @@ static u32 prestera_fix_tb_id(u32 tb_id)
51
53
}
52
54
53
55
static void
54
- prestera_util_fen_info2fib_cache_key (struct fib_entry_notifier_info * fen_info ,
56
+ prestera_util_fen_info2fib_cache_key (struct fib_notifier_info * info ,
55
57
struct prestera_kern_fib_cache_key * key )
56
58
{
59
+ struct fib_entry_notifier_info * fen_info =
60
+ container_of (info , struct fib_entry_notifier_info , info );
61
+
57
62
memset (key , 0 , sizeof (* key ));
63
+ key -> addr .v = PRESTERA_IPV4 ;
58
64
key -> addr .u .ipv4 = cpu_to_be32 (fen_info -> dst );
59
65
key -> prefix_len = fen_info -> dst_len ;
60
66
key -> kern_tb_id = fen_info -> tb_id ;
61
67
}
62
68
69
+ static unsigned char
70
+ prestera_kern_fib_info_type (struct fib_notifier_info * info )
71
+ {
72
+ struct fib6_entry_notifier_info * fen6_info ;
73
+ struct fib_entry_notifier_info * fen4_info ;
74
+
75
+ if (info -> family == AF_INET ) {
76
+ fen4_info = container_of (info , struct fib_entry_notifier_info ,
77
+ info );
78
+ return fen4_info -> fi -> fib_type ;
79
+ } else if (info -> family == AF_INET6 ) {
80
+ fen6_info = container_of (info , struct fib6_entry_notifier_info ,
81
+ info );
82
+ /* TODO: ECMP in ipv6 is several routes.
83
+ * Every route has single nh.
84
+ */
85
+ return fen6_info -> rt -> fib6_type ;
86
+ }
87
+
88
+ return RTN_UNSPEC ;
89
+ }
90
+
63
91
static struct prestera_kern_fib_cache *
64
92
prestera_kern_fib_cache_find (struct prestera_switch * sw ,
65
93
struct prestera_kern_fib_cache_key * key )
@@ -76,7 +104,7 @@ static void
76
104
__prestera_kern_fib_cache_destruct (struct prestera_switch * sw ,
77
105
struct prestera_kern_fib_cache * fib_cache )
78
106
{
79
- fib_info_put (fib_cache -> fi );
107
+ fib_info_put (fib_cache -> fen4_info . fi );
80
108
}
81
109
82
110
static void
@@ -96,8 +124,10 @@ prestera_kern_fib_cache_destroy(struct prestera_switch *sw,
96
124
static struct prestera_kern_fib_cache *
97
125
prestera_kern_fib_cache_create (struct prestera_switch * sw ,
98
126
struct prestera_kern_fib_cache_key * key ,
99
- struct fib_info * fi , dscp_t dscp , u8 type )
127
+ struct fib_notifier_info * info )
100
128
{
129
+ struct fib_entry_notifier_info * fen_info =
130
+ container_of (info , struct fib_entry_notifier_info , info );
101
131
struct prestera_kern_fib_cache * fib_cache ;
102
132
int err ;
103
133
@@ -106,10 +136,8 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw,
106
136
goto err_kzalloc ;
107
137
108
138
memcpy (& fib_cache -> key , key , sizeof (* key ));
109
- fib_info_hold (fi );
110
- fib_cache -> fi = fi ;
111
- fib_cache -> kern_dscp = dscp ;
112
- fib_cache -> kern_type = type ;
139
+ fib_info_hold (fen_info -> fi );
140
+ memcpy (& fib_cache -> fen4_info , fen_info , sizeof (* fen_info ));
113
141
114
142
err = rhashtable_insert_fast (& sw -> router -> kern_fib_cache_ht ,
115
143
& fib_cache -> ht_node ,
@@ -120,7 +148,7 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw,
120
148
return fib_cache ;
121
149
122
150
err_ht_insert :
123
- fib_info_put (fi );
151
+ fib_info_put (fen_info -> fi );
124
152
kfree (fib_cache );
125
153
err_kzalloc :
126
154
return NULL ;
@@ -133,21 +161,25 @@ __prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw,
133
161
{
134
162
struct fib_rt_info fri ;
135
163
136
- if (fc -> key .addr .v != PRESTERA_IPV4 )
164
+ switch (fc -> key .addr .v ) {
165
+ case PRESTERA_IPV4 :
166
+ fri .fi = fc -> fen4_info .fi ;
167
+ fri .tb_id = fc -> key .kern_tb_id ;
168
+ fri .dst = fc -> key .addr .u .ipv4 ;
169
+ fri .dst_len = fc -> key .prefix_len ;
170
+ fri .dscp = fc -> fen4_info .dscp ;
171
+ fri .type = fc -> fen4_info .type ;
172
+ /* flags begin */
173
+ fri .offload = offload ;
174
+ fri .trap = trap ;
175
+ fri .offload_failed = fail ;
176
+ /* flags end */
177
+ fib_alias_hw_flags_set (& init_net , & fri );
137
178
return ;
138
-
139
- fri .fi = fc -> fi ;
140
- fri .tb_id = fc -> key .kern_tb_id ;
141
- fri .dst = fc -> key .addr .u .ipv4 ;
142
- fri .dst_len = fc -> key .prefix_len ;
143
- fri .dscp = fc -> kern_dscp ;
144
- fri .type = fc -> kern_type ;
145
- /* flags begin */
146
- fri .offload = offload ;
147
- fri .trap = trap ;
148
- fri .offload_failed = fail ;
149
- /* flags end */
150
- fib_alias_hw_flags_set (& init_net , & fri );
179
+ case PRESTERA_IPV6 :
180
+ /* TODO */
181
+ return ;
182
+ }
151
183
}
152
184
153
185
static int
@@ -156,7 +188,7 @@ __prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch *sw,
156
188
{
157
189
memset (& fc -> lpm_info , 0 , sizeof (fc -> lpm_info ));
158
190
159
- switch (fc -> fi -> fib_type ) {
191
+ switch (prestera_kern_fib_info_type ( & fc -> info ) ) {
160
192
case RTN_UNICAST :
161
193
fc -> lpm_info .fib_type = PRESTERA_FIB_TYPE_TRAP ;
162
194
break ;
@@ -283,14 +315,14 @@ __prestera_k_arb_util_fib_overlapped(struct prestera_switch *sw,
283
315
static int
284
316
prestera_k_arb_fib_evt (struct prestera_switch * sw ,
285
317
bool replace , /* replace or del */
286
- struct fib_entry_notifier_info * fen_info )
318
+ struct fib_notifier_info * info )
287
319
{
288
320
struct prestera_kern_fib_cache * tfib_cache , * bfib_cache ; /* top/btm */
289
321
struct prestera_kern_fib_cache_key fc_key ;
290
322
struct prestera_kern_fib_cache * fib_cache ;
291
323
int err ;
292
324
293
- prestera_util_fen_info2fib_cache_key (fen_info , & fc_key );
325
+ prestera_util_fen_info2fib_cache_key (info , & fc_key );
294
326
fib_cache = prestera_kern_fib_cache_find (sw , & fc_key );
295
327
if (fib_cache ) {
296
328
fib_cache -> reachable = false;
@@ -313,10 +345,7 @@ prestera_k_arb_fib_evt(struct prestera_switch *sw,
313
345
}
314
346
315
347
if (replace ) {
316
- fib_cache = prestera_kern_fib_cache_create (sw , & fc_key ,
317
- fen_info -> fi ,
318
- fen_info -> dscp ,
319
- fen_info -> type );
348
+ fib_cache = prestera_kern_fib_cache_create (sw , & fc_key , info );
320
349
if (!fib_cache ) {
321
350
dev_err (sw -> dev -> dev , "fib_cache == NULL" );
322
351
return - ENOENT ;
@@ -508,13 +537,15 @@ static void __prestera_router_fib_event_work(struct work_struct *work)
508
537
509
538
switch (fib_work -> event ) {
510
539
case FIB_EVENT_ENTRY_REPLACE :
511
- err = prestera_k_arb_fib_evt (sw , true, & fib_work -> fen_info );
540
+ err = prestera_k_arb_fib_evt (sw , true,
541
+ & fib_work -> fen_info .info );
512
542
if (err )
513
543
goto err_out ;
514
544
515
545
break ;
516
546
case FIB_EVENT_ENTRY_DEL :
517
- err = prestera_k_arb_fib_evt (sw , false, & fib_work -> fen_info );
547
+ err = prestera_k_arb_fib_evt (sw , false,
548
+ & fib_work -> fen_info .info );
518
549
if (err )
519
550
goto err_out ;
520
551
0 commit comments