77#include <net/inet_dscp.h>
88#include <net/switchdev.h>
99#include <linux/rhashtable.h>
10+ #include <net/nexthop.h>
1011
1112#include "prestera.h"
1213#include "prestera_router_hw.h"
@@ -26,9 +27,10 @@ struct prestera_kern_fib_cache {
2627 } lpm_info ; /* hold prepared lpm info */
2728 /* Indicate if route is not overlapped by another table */
2829 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+ };
3234 bool reachable ;
3335};
3436
@@ -51,15 +53,41 @@ static u32 prestera_fix_tb_id(u32 tb_id)
5153}
5254
5355static 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 ,
5557 struct prestera_kern_fib_cache_key * key )
5658{
59+ struct fib_entry_notifier_info * fen_info =
60+ container_of (info , struct fib_entry_notifier_info , info );
61+
5762 memset (key , 0 , sizeof (* key ));
63+ key -> addr .v = PRESTERA_IPV4 ;
5864 key -> addr .u .ipv4 = cpu_to_be32 (fen_info -> dst );
5965 key -> prefix_len = fen_info -> dst_len ;
6066 key -> kern_tb_id = fen_info -> tb_id ;
6167}
6268
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+
6391static struct prestera_kern_fib_cache *
6492prestera_kern_fib_cache_find (struct prestera_switch * sw ,
6593 struct prestera_kern_fib_cache_key * key )
@@ -76,7 +104,7 @@ static void
76104__prestera_kern_fib_cache_destruct (struct prestera_switch * sw ,
77105 struct prestera_kern_fib_cache * fib_cache )
78106{
79- fib_info_put (fib_cache -> fi );
107+ fib_info_put (fib_cache -> fen4_info . fi );
80108}
81109
82110static void
@@ -96,8 +124,10 @@ prestera_kern_fib_cache_destroy(struct prestera_switch *sw,
96124static struct prestera_kern_fib_cache *
97125prestera_kern_fib_cache_create (struct prestera_switch * sw ,
98126 struct prestera_kern_fib_cache_key * key ,
99- struct fib_info * fi , dscp_t dscp , u8 type )
127+ struct fib_notifier_info * info )
100128{
129+ struct fib_entry_notifier_info * fen_info =
130+ container_of (info , struct fib_entry_notifier_info , info );
101131 struct prestera_kern_fib_cache * fib_cache ;
102132 int err ;
103133
@@ -106,10 +136,8 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw,
106136 goto err_kzalloc ;
107137
108138 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 ));
113141
114142 err = rhashtable_insert_fast (& sw -> router -> kern_fib_cache_ht ,
115143 & fib_cache -> ht_node ,
@@ -120,7 +148,7 @@ prestera_kern_fib_cache_create(struct prestera_switch *sw,
120148 return fib_cache ;
121149
122150err_ht_insert :
123- fib_info_put (fi );
151+ fib_info_put (fen_info -> fi );
124152 kfree (fib_cache );
125153err_kzalloc :
126154 return NULL ;
@@ -133,21 +161,25 @@ __prestera_k_arb_fib_lpm_offload_set(struct prestera_switch *sw,
133161{
134162 struct fib_rt_info fri ;
135163
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 );
137178 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+ }
151183}
152184
153185static int
@@ -156,7 +188,7 @@ __prestera_pr_k_arb_fc_lpm_info_calc(struct prestera_switch *sw,
156188{
157189 memset (& fc -> lpm_info , 0 , sizeof (fc -> lpm_info ));
158190
159- switch (fc -> fi -> fib_type ) {
191+ switch (prestera_kern_fib_info_type ( & fc -> info ) ) {
160192 case RTN_UNICAST :
161193 fc -> lpm_info .fib_type = PRESTERA_FIB_TYPE_TRAP ;
162194 break ;
@@ -283,14 +315,14 @@ __prestera_k_arb_util_fib_overlapped(struct prestera_switch *sw,
283315static int
284316prestera_k_arb_fib_evt (struct prestera_switch * sw ,
285317 bool replace , /* replace or del */
286- struct fib_entry_notifier_info * fen_info )
318+ struct fib_notifier_info * info )
287319{
288320 struct prestera_kern_fib_cache * tfib_cache , * bfib_cache ; /* top/btm */
289321 struct prestera_kern_fib_cache_key fc_key ;
290322 struct prestera_kern_fib_cache * fib_cache ;
291323 int err ;
292324
293- prestera_util_fen_info2fib_cache_key (fen_info , & fc_key );
325+ prestera_util_fen_info2fib_cache_key (info , & fc_key );
294326 fib_cache = prestera_kern_fib_cache_find (sw , & fc_key );
295327 if (fib_cache ) {
296328 fib_cache -> reachable = false;
@@ -313,10 +345,7 @@ prestera_k_arb_fib_evt(struct prestera_switch *sw,
313345 }
314346
315347 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 );
320349 if (!fib_cache ) {
321350 dev_err (sw -> dev -> dev , "fib_cache == NULL" );
322351 return - ENOENT ;
@@ -508,13 +537,15 @@ static void __prestera_router_fib_event_work(struct work_struct *work)
508537
509538 switch (fib_work -> event ) {
510539 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 );
512542 if (err )
513543 goto err_out ;
514544
515545 break ;
516546 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 );
518549 if (err )
519550 goto err_out ;
520551
0 commit comments