]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_neigh.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Zebra neighbor table management
5 * Copyright (C) 2021 Nvidia
22 #include "zebra/zebra_router.h"
23 #include "zebra/debug.h"
24 #include "zebra/interface.h"
25 #include "zebra/rib.h"
27 #include "zebra/rt_netlink.h"
28 #include "zebra/zebra_errors.h"
29 #include "zebra/interface.h"
30 #include "zebra/zebra_neigh.h"
31 #include "zebra/zebra_pbr.h"
33 DEFINE_MTYPE_STATIC(ZEBRA
, ZNEIGH_INFO
, "Zebra neigh table");
34 DEFINE_MTYPE_STATIC(ZEBRA
, ZNEIGH_ENT
, "Zebra neigh entry");
36 static int zebra_neigh_rb_cmp(const struct zebra_neigh_ent
*n1
,
37 const struct zebra_neigh_ent
*n2
)
39 if (n1
->ifindex
< n2
->ifindex
)
42 if (n1
->ifindex
> n2
->ifindex
)
45 if (n1
->ip
.ipa_type
< n2
->ip
.ipa_type
)
48 if (n1
->ip
.ipa_type
> n2
->ip
.ipa_type
)
51 if (n1
->ip
.ipa_type
== AF_INET
) {
52 if (n1
->ip
.ipaddr_v4
.s_addr
< n2
->ip
.ipaddr_v4
.s_addr
)
55 if (n1
->ip
.ipaddr_v4
.s_addr
> n2
->ip
.ipaddr_v4
.s_addr
)
61 return memcmp(&n1
->ip
.ipaddr_v6
, &n2
->ip
.ipaddr_v6
, IPV6_MAX_BYTELEN
);
63 RB_GENERATE(zebra_neigh_rb_head
, zebra_neigh_ent
, rb_node
, zebra_neigh_rb_cmp
);
65 static struct zebra_neigh_ent
*zebra_neigh_find(ifindex_t ifindex
,
68 struct zebra_neigh_ent tmp
;
70 tmp
.ifindex
= ifindex
;
71 memcpy(&tmp
.ip
, ip
, sizeof(*ip
));
72 return RB_FIND(zebra_neigh_rb_head
, &zneigh_info
->neigh_rb_tree
, &tmp
);
75 static struct zebra_neigh_ent
*
76 zebra_neigh_new(ifindex_t ifindex
, struct ipaddr
*ip
, struct ethaddr
*mac
)
78 struct zebra_neigh_ent
*n
;
80 n
= XCALLOC(MTYPE_ZNEIGH_ENT
, sizeof(struct zebra_neigh_ent
));
82 memcpy(&n
->ip
, ip
, sizeof(*ip
));
85 memcpy(&n
->mac
, mac
, sizeof(*mac
));
86 n
->flags
|= ZEBRA_NEIGH_ENT_ACTIVE
;
90 if (RB_INSERT(zebra_neigh_rb_head
, &zneigh_info
->neigh_rb_tree
, n
)) {
91 XFREE(MTYPE_ZNEIGH_ENT
, n
);
95 /* Initialise the pbr rule list */
96 n
->pbr_rule_list
= list_new();
97 listset_app_node_mem(n
->pbr_rule_list
);
99 if (IS_ZEBRA_DEBUG_NEIGH
)
100 zlog_debug("zebra neigh new if %d %pIA %pEA", n
->ifindex
,
106 static void zebra_neigh_pbr_rules_update(struct zebra_neigh_ent
*n
)
108 struct zebra_pbr_rule
*rule
;
109 struct listnode
*node
;
111 for (ALL_LIST_ELEMENTS_RO(n
->pbr_rule_list
, node
, rule
))
112 dplane_pbr_rule_update(rule
, rule
);
115 static void zebra_neigh_free(struct zebra_neigh_ent
*n
)
117 if (listcount(n
->pbr_rule_list
)) {
118 /* if rules are still using the neigh mark it as inactive and
119 * update the dataplane
121 if (n
->flags
& ZEBRA_NEIGH_ENT_ACTIVE
) {
122 n
->flags
&= ~ZEBRA_NEIGH_ENT_ACTIVE
;
123 memset(&n
->mac
, 0, sizeof(n
->mac
));
125 zebra_neigh_pbr_rules_update(n
);
128 if (IS_ZEBRA_DEBUG_NEIGH
)
129 zlog_debug("zebra neigh free if %d %pIA %pEA", n
->ifindex
,
132 /* cleanup resources maintained against the neigh */
133 list_delete(&n
->pbr_rule_list
);
135 RB_REMOVE(zebra_neigh_rb_head
, &zneigh_info
->neigh_rb_tree
, n
);
137 XFREE(MTYPE_ZNEIGH_ENT
, n
);
140 /* kernel neigh del */
141 void zebra_neigh_del(struct interface
*ifp
, struct ipaddr
*ip
)
143 struct zebra_neigh_ent
*n
;
145 if (IS_ZEBRA_DEBUG_NEIGH
)
146 zlog_debug("zebra neigh del if %s/%d %pIA", ifp
->name
,
149 n
= zebra_neigh_find(ifp
->ifindex
, ip
);
155 /* kernel neigh add */
156 void zebra_neigh_add(struct interface
*ifp
, struct ipaddr
*ip
,
159 struct zebra_neigh_ent
*n
;
161 if (IS_ZEBRA_DEBUG_NEIGH
)
162 zlog_debug("zebra neigh add if %s/%d %pIA %pEA", ifp
->name
,
163 ifp
->ifindex
, ip
, mac
);
165 n
= zebra_neigh_find(ifp
->ifindex
, ip
);
167 if (!memcmp(&n
->mac
, mac
, sizeof(*mac
)))
170 memcpy(&n
->mac
, mac
, sizeof(*mac
));
171 n
->flags
|= ZEBRA_NEIGH_ENT_ACTIVE
;
173 /* update rules linked to the neigh */
174 zebra_neigh_pbr_rules_update(n
);
176 zebra_neigh_new(ifp
->ifindex
, ip
, mac
);
180 void zebra_neigh_deref(struct zebra_pbr_rule
*rule
)
182 struct zebra_neigh_ent
*n
= rule
->action
.neigh
;
184 if (IS_ZEBRA_DEBUG_NEIGH
)
185 zlog_debug("zebra neigh deref if %d %pIA by pbr rule %u",
186 n
->ifindex
, &n
->ip
, rule
->rule
.seq
);
188 rule
->action
.neigh
= NULL
;
189 /* remove rule from the list and free if it is inactive */
190 list_delete_node(n
->pbr_rule_list
, &rule
->action
.neigh_listnode
);
191 if (!(n
->flags
& ZEBRA_NEIGH_ENT_ACTIVE
))
195 /* XXX - this needs to work with evpn's neigh read */
196 static void zebra_neigh_read_on_first_ref(void)
198 static bool neigh_read_done
;
200 if (!neigh_read_done
) {
201 neigh_read(zebra_ns_lookup(NS_DEFAULT
));
202 neigh_read_done
= true;
206 void zebra_neigh_ref(int ifindex
, struct ipaddr
*ip
,
207 struct zebra_pbr_rule
*rule
)
209 struct zebra_neigh_ent
*n
;
211 if (IS_ZEBRA_DEBUG_NEIGH
)
212 zlog_debug("zebra neigh ref if %d %pIA by pbr rule %u", ifindex
,
215 zebra_neigh_read_on_first_ref();
216 n
= zebra_neigh_find(ifindex
, ip
);
218 n
= zebra_neigh_new(ifindex
, ip
, NULL
);
220 /* link the pbr entry to the neigh */
221 if (rule
->action
.neigh
== n
)
224 if (rule
->action
.neigh
)
225 zebra_neigh_deref(rule
);
227 rule
->action
.neigh
= n
;
228 listnode_init(&rule
->action
.neigh_listnode
, rule
);
229 listnode_add(n
->pbr_rule_list
, &rule
->action
.neigh_listnode
);
232 static void zebra_neigh_show_one(struct vty
*vty
, struct zebra_neigh_ent
*n
)
234 char mac_buf
[ETHER_ADDR_STRLEN
];
235 char ip_buf
[INET6_ADDRSTRLEN
];
236 struct interface
*ifp
;
238 ifp
= if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT
),
240 ipaddr2str(&n
->ip
, ip_buf
, sizeof(ip_buf
));
241 prefix_mac2str(&n
->mac
, mac_buf
, sizeof(mac_buf
));
242 vty_out(vty
, "%-20s %-30s %-18s %u\n", ifp
? ifp
->name
: "-", ip_buf
,
243 mac_buf
, listcount(n
->pbr_rule_list
));
246 void zebra_neigh_show(struct vty
*vty
)
248 struct zebra_neigh_ent
*n
;
250 vty_out(vty
, "%-20s %-30s %-18s %s\n", "Interface", "Neighbor", "MAC",
252 RB_FOREACH (n
, zebra_neigh_rb_head
, &zneigh_info
->neigh_rb_tree
)
253 zebra_neigh_show_one(vty
, n
);
256 void zebra_neigh_init(void)
258 zneigh_info
= XCALLOC(MTYPE_ZNEIGH_INFO
, sizeof(*zrouter
.neigh_info
));
259 RB_INIT(zebra_neigh_rb_head
, &zneigh_info
->neigh_rb_tree
);
262 void zebra_neigh_terminate(void)
264 struct zebra_neigh_ent
*n
, *next
;
266 if (!zrouter
.neigh_info
)
269 RB_FOREACH_SAFE (n
, zebra_neigh_rb_head
, &zneigh_info
->neigh_rb_tree
,
272 XFREE(MTYPE_ZNEIGH_INFO
, zneigh_info
);