]> git.proxmox.com Git - mirror_frr.git/blob - pbrd/pbr_zebra.c
Merge pull request #2077 from donaldsharp/static_warn
[mirror_frr.git] / pbrd / pbr_zebra.c
1 /*
2 * Zebra connect code.
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRR is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <zebra.h>
21
22 #include "thread.h"
23 #include "command.h"
24 #include "network.h"
25 #include "prefix.h"
26 #include "routemap.h"
27 #include "table.h"
28 #include "stream.h"
29 #include "memory.h"
30 #include "zclient.h"
31 #include "filter.h"
32 #include "plist.h"
33 #include "log.h"
34 #include "nexthop.h"
35 #include "nexthop_group.h"
36
37 #include "pbr_nht.h"
38 #include "pbr_map.h"
39 #include "pbr_memory.h"
40 #include "pbr_zebra.h"
41 #include "pbr_debug.h"
42
43 DEFINE_MTYPE_STATIC(PBRD, PBR_INTERFACE, "PBR Interface")
44
45 /* Zebra structure to hold current status. */
46 struct zclient *zclient;
47
48 struct pbr_interface *pbr_if_new(struct interface *ifp)
49 {
50 struct pbr_interface *pbr_ifp;
51
52 zassert(ifp);
53 zassert(!ifp->info);
54
55 pbr_ifp = XCALLOC(MTYPE_PBR_INTERFACE, sizeof(*pbr_ifp));
56
57 if (!pbr_ifp) {
58 zlog_err("%s: PBR XCALLOC(%zu) failure", __PRETTY_FUNCTION__,
59 sizeof(*pbr_ifp));
60 return 0;
61 }
62
63 return (pbr_ifp);
64 }
65
66 /* Inteface addition message from zebra. */
67 static int interface_add(int command, struct zclient *zclient,
68 zebra_size_t length, vrf_id_t vrf_id)
69 {
70 struct interface *ifp;
71
72 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
73
74 if (!ifp)
75 return 0;
76
77 if (!ifp->info) {
78 struct pbr_interface *pbr_ifp;
79
80 pbr_ifp = pbr_if_new(ifp);
81 ifp->info = pbr_ifp;
82 }
83
84 return 0;
85 }
86
87 static int interface_delete(int command, struct zclient *zclient,
88 zebra_size_t length, vrf_id_t vrf_id)
89 {
90 struct interface *ifp;
91 struct stream *s;
92
93 s = zclient->ibuf;
94 /* zebra_interface_state_read () updates interface structure in iflist
95 */
96 ifp = zebra_interface_state_read(s, vrf_id);
97
98 if (ifp == NULL)
99 return 0;
100
101 if_set_index(ifp, IFINDEX_INTERNAL);
102
103 return 0;
104 }
105
106 static int interface_address_add(int command, struct zclient *zclient,
107 zebra_size_t length, vrf_id_t vrf_id)
108 {
109 zebra_interface_address_read(command, zclient->ibuf, vrf_id);
110
111 return 0;
112 }
113
114 static int interface_address_delete(int command, struct zclient *zclient,
115 zebra_size_t length, vrf_id_t vrf_id)
116 {
117 struct connected *c;
118
119 c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
120
121 if (!c)
122 return 0;
123
124 connected_free(c);
125 return 0;
126 }
127
128 static int interface_state_up(int command, struct zclient *zclient,
129 zebra_size_t length, vrf_id_t vrf_id)
130 {
131
132 zebra_interface_state_read(zclient->ibuf, vrf_id);
133
134 return 0;
135 }
136
137 static int interface_state_down(int command, struct zclient *zclient,
138 zebra_size_t length, vrf_id_t vrf_id)
139 {
140
141 zebra_interface_state_read(zclient->ibuf, vrf_id);
142
143 return 0;
144 }
145
146 static int route_notify_owner(int command, struct zclient *zclient,
147 zebra_size_t length, vrf_id_t vrf_id)
148 {
149 struct prefix p;
150 enum zapi_route_notify_owner note;
151 uint32_t table_id;
152 char buf[PREFIX_STRLEN];
153
154 prefix2str(&p, buf, sizeof(buf));
155
156 if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note))
157 return -1;
158
159 switch (note) {
160 case ZAPI_ROUTE_FAIL_INSTALL:
161 DEBUGD(&pbr_dbg_zebra,
162 "%s: [%s] Route install failure for table: %u",
163 __PRETTY_FUNCTION__, buf, table_id);
164 break;
165 case ZAPI_ROUTE_BETTER_ADMIN_WON:
166 DEBUGD(&pbr_dbg_zebra,
167 "%s: [%s] Route better admin distance won for table: %u",
168 __PRETTY_FUNCTION__, buf, table_id);
169 break;
170 case ZAPI_ROUTE_INSTALLED:
171 DEBUGD(&pbr_dbg_zebra,
172 "%s: [%s] Route installed succeeded for table: %u",
173 __PRETTY_FUNCTION__, buf, table_id);
174 pbr_nht_route_installed_for_table(table_id);
175 break;
176 case ZAPI_ROUTE_REMOVED:
177 DEBUGD(&pbr_dbg_zebra,
178 "%s: [%s] Route Removed succeeded for table: %u",
179 __PRETTY_FUNCTION__, buf, table_id);
180 pbr_nht_route_removed_for_table(table_id);
181 break;
182 case ZAPI_ROUTE_REMOVE_FAIL:
183 DEBUGD(&pbr_dbg_zebra,
184 "%s: [%s] Route remove fail for table: %u",
185 __PRETTY_FUNCTION__, buf, table_id);
186 break;
187 }
188
189 return 0;
190 }
191
192 static int rule_notify_owner(int command, struct zclient *zclient,
193 zebra_size_t length, vrf_id_t vrf_id)
194 {
195 uint32_t seqno, priority, unique;
196 enum zapi_rule_notify_owner note;
197 struct pbr_map_sequence *pbrms;
198 struct pbr_map_interface *pmi;
199 ifindex_t ifi;
200 uint64_t installed;
201
202 if (!zapi_rule_notify_decode(zclient->ibuf, &seqno, &priority, &unique,
203 &ifi, &note))
204 return -1;
205
206 pmi = NULL;
207 pbrms = pbrms_lookup_unique(unique, ifi, &pmi);
208 if (!pbrms) {
209 DEBUGD(&pbr_dbg_zebra,
210 "%s: Failure to lookup pbrms based upon %u",
211 __PRETTY_FUNCTION__, unique);
212 return 0;
213 }
214
215 installed = 1 << pmi->install_bit;
216
217 switch (note) {
218 case ZAPI_RULE_FAIL_INSTALL:
219 DEBUGD(&pbr_dbg_zebra, "%s: Recieved RULE_FAIL_INSTALL",
220 __PRETTY_FUNCTION__);
221 pbrms->installed &= ~installed;
222 break;
223 case ZAPI_RULE_INSTALLED:
224 pbrms->installed |= installed;
225 DEBUGD(&pbr_dbg_zebra, "%s: Recived RULE_INSTALLED",
226 __PRETTY_FUNCTION__);
227 break;
228 case ZAPI_RULE_REMOVED:
229 pbrms->installed &= ~installed;
230 DEBUGD(&pbr_dbg_zebra, "%s: Received RULE REMOVED",
231 __PRETTY_FUNCTION__);
232 break;
233 }
234
235 return 0;
236 }
237
238 static void zebra_connected(struct zclient *zclient)
239 {
240 zclient_send_reg_requests(zclient, VRF_DEFAULT);
241 }
242
243 static void route_add_helper(struct zapi_route *api, struct nexthop_group nhg,
244 uint8_t install_afi)
245 {
246 struct zapi_nexthop *api_nh;
247 struct nexthop *nhop;
248 int i;
249
250 api->prefix.family = install_afi;
251
252 i = 0;
253 for (ALL_NEXTHOPS(nhg, nhop)) {
254 api_nh = &api->nexthops[i];
255 api_nh->vrf_id = nhop->vrf_id;
256 api_nh->type = nhop->type;
257 switch (nhop->type) {
258 case NEXTHOP_TYPE_IPV4:
259 api_nh->gate.ipv4 = nhop->gate.ipv4;
260 break;
261 case NEXTHOP_TYPE_IPV4_IFINDEX:
262 api_nh->gate.ipv4 = nhop->gate.ipv4;
263 api_nh->ifindex = nhop->ifindex;
264 break;
265 case NEXTHOP_TYPE_IFINDEX:
266 api_nh->ifindex = nhop->ifindex;
267 break;
268 case NEXTHOP_TYPE_IPV6:
269 memcpy(&api_nh->gate.ipv6, &nhop->gate.ipv6, 16);
270 break;
271 case NEXTHOP_TYPE_IPV6_IFINDEX:
272 api_nh->ifindex = nhop->ifindex;
273 memcpy(&api_nh->gate.ipv6, &nhop->gate.ipv6, 16);
274 break;
275 case NEXTHOP_TYPE_BLACKHOLE:
276 api_nh->bh_type = nhop->bh_type;
277 break;
278 }
279 i++;
280 }
281 api->nexthop_num = i;
282
283 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, api);
284 }
285
286 /*
287 * This function assumes a default route is being
288 * installed into the appropriate tableid
289 */
290 void route_add(struct pbr_nexthop_group_cache *pnhgc, struct nexthop_group nhg,
291 afi_t install_afi)
292 {
293 struct zapi_route api;
294
295 memset(&api, 0, sizeof(api));
296
297 api.vrf_id = VRF_DEFAULT;
298 api.type = ZEBRA_ROUTE_PBR;
299 api.safi = SAFI_UNICAST;
300 /*
301 * Sending a default route
302 */
303 api.tableid = pnhgc->table_id;
304 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
305 SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
306 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
307 switch (install_afi) {
308 case AFI_MAX:
309 route_add_helper(&api, nhg, AF_INET);
310 route_add_helper(&api, nhg, AF_INET6);
311 break;
312 case AFI_IP:
313 route_add_helper(&api, nhg, AF_INET);
314 break;
315 case AFI_IP6:
316 route_add_helper(&api, nhg, AF_INET6);
317 break;
318 case AFI_L2VPN:
319 DEBUGD(&pbr_dbg_zebra,
320 "%s: Asked to install unsupported route type: L2VPN",
321 __PRETTY_FUNCTION__);
322 break;
323 }
324 }
325
326 /*
327 * This function assumes a default route is being
328 * removed from the appropriate tableid
329 */
330 void route_delete(struct pbr_nexthop_group_cache *pnhgc, afi_t afi)
331 {
332 struct zapi_route api;
333
334 memset(&api, 0, sizeof(api));
335 api.vrf_id = VRF_DEFAULT;
336 api.type = ZEBRA_ROUTE_PBR;
337 api.safi = SAFI_UNICAST;
338
339 api.tableid = pnhgc->table_id;
340 SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
341
342 switch (afi) {
343 case AFI_IP:
344 api.prefix.family = AF_INET;
345 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
346 break;
347 case AFI_IP6:
348 api.prefix.family = AF_INET6;
349 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
350 break;
351 case AFI_MAX:
352 api.prefix.family = AF_INET;
353 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
354 api.prefix.family = AF_INET6;
355 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
356 break;
357 case AFI_L2VPN:
358 DEBUGD(&pbr_dbg_zebra,
359 "%s: Asked to delete unsupported route type: L2VPN",
360 __PRETTY_FUNCTION__);
361 break;
362 }
363 }
364
365 static int pbr_zebra_nexthop_update(int command, struct zclient *zclient,
366 zebra_size_t length, vrf_id_t vrf_id)
367 {
368 struct zapi_route nhr;
369 char buf[PREFIX2STR_BUFFER];
370 uint32_t i;
371
372 zapi_nexthop_update_decode(zclient->ibuf, &nhr);
373
374 if (DEBUG_MODE_CHECK(&pbr_dbg_zebra, DEBUG_MODE_ALL)) {
375
376 DEBUGD(&pbr_dbg_zebra, "%s: Received Nexthop update: %s",
377 __PRETTY_FUNCTION__,
378 prefix2str(&nhr.prefix, buf, sizeof(buf)));
379
380 DEBUGD(&pbr_dbg_zebra, "%s: (\tNexthops(%u)",
381 __PRETTY_FUNCTION__, nhr.nexthop_num);
382
383 for (i = 0; i < nhr.nexthop_num; i++) {
384 DEBUGD(&pbr_dbg_zebra,
385 "%s: \tType: %d: vrf: %d, ifindex: %d gate: %s",
386 __PRETTY_FUNCTION__, nhr.nexthops[i].type,
387 nhr.nexthops[i].vrf_id, nhr.nexthops[i].ifindex,
388 inet_ntoa(nhr.nexthops[i].gate.ipv4));
389 }
390 }
391
392 pbr_nht_nexthop_update(&nhr);
393 return 1;
394 }
395
396 extern struct zebra_privs_t pbr_privs;
397
398 void pbr_zebra_init(void)
399 {
400 struct zclient_options opt = { .receive_notify = true };
401
402 zclient = zclient_new_notify(master, &opt);
403
404 zclient_init(zclient, ZEBRA_ROUTE_PBR, 0, &pbr_privs);
405 zclient->zebra_connected = zebra_connected;
406 zclient->interface_add = interface_add;
407 zclient->interface_delete = interface_delete;
408 zclient->interface_up = interface_state_up;
409 zclient->interface_down = interface_state_down;
410 zclient->interface_address_add = interface_address_add;
411 zclient->interface_address_delete = interface_address_delete;
412 zclient->route_notify_owner = route_notify_owner;
413 zclient->rule_notify_owner = rule_notify_owner;
414 zclient->nexthop_update = pbr_zebra_nexthop_update;
415 }
416
417 void pbr_send_rnh(struct nexthop *nhop, bool reg)
418 {
419 uint32_t command;
420 struct prefix p;
421
422 command = (reg) ?
423 ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER;
424
425 memset(&p, 0, sizeof(p));
426 switch (nhop->type) {
427 case NEXTHOP_TYPE_IFINDEX:
428 case NEXTHOP_TYPE_BLACKHOLE:
429 return;
430 case NEXTHOP_TYPE_IPV4:
431 case NEXTHOP_TYPE_IPV4_IFINDEX:
432 p.family = AF_INET;
433 p.u.prefix4.s_addr = nhop->gate.ipv4.s_addr;
434 p.prefixlen = 32;
435 break;
436 case NEXTHOP_TYPE_IPV6:
437 case NEXTHOP_TYPE_IPV6_IFINDEX:
438 p.family = AF_INET6;
439 memcpy(&p.u.prefix6, &nhop->gate.ipv6, 16);
440 p.prefixlen = 128;
441 break;
442 }
443
444 if (zclient_send_rnh(zclient, command, &p,
445 false, nhop->vrf_id) < 0) {
446 zlog_warn("%s: Failure to send nexthop to zebra",
447 __PRETTY_FUNCTION__);
448 }
449 }
450
451 static void pbr_encode_pbr_map_sequence_prefix(struct stream *s,
452 struct prefix *p,
453 unsigned char family)
454 {
455 struct prefix any;
456
457 if (!p) {
458 memset(&any, 0, sizeof(any));
459 any.family = family;
460 p = &any;
461 }
462
463 stream_putc(s, p->family);
464 stream_putc(s, p->prefixlen);
465 stream_put(s, &p->u.prefix, prefix_blen(p));
466 }
467
468 static void pbr_encode_pbr_map_sequence(struct stream *s,
469 struct pbr_map_sequence *pbrms,
470 struct interface *ifp)
471 {
472 unsigned char family;
473
474 family = AF_INET;
475 if (pbrms->family)
476 family = pbrms->family;
477
478 stream_putl(s, pbrms->seqno);
479 stream_putl(s, pbrms->ruleno);
480 stream_putl(s, pbrms->unique);
481 pbr_encode_pbr_map_sequence_prefix(s, pbrms->src, family);
482 stream_putw(s, 0); /* src port */
483 pbr_encode_pbr_map_sequence_prefix(s, pbrms->dst, family);
484 stream_putw(s, 0); /* dst port */
485 if (pbrms->nhgrp_name)
486 stream_putl(s, pbr_nht_get_table(pbrms->nhgrp_name));
487 else if (pbrms->nhg)
488 stream_putl(s, pbr_nht_get_table(pbrms->internal_nhg_name));
489 stream_putl(s, ifp->ifindex);
490 }
491
492 void pbr_send_pbr_map(struct pbr_map_sequence *pbrms,
493 struct pbr_map_interface *pmi, bool install)
494 {
495 struct pbr_map *pbrm = pbrms->parent;
496 struct stream *s;
497 uint64_t is_installed = 1 << pmi->install_bit;
498
499 is_installed &= pbrms->installed;
500
501 DEBUGD(&pbr_dbg_zebra, "%s: for %s %d(%" PRIu64 ")",
502 __PRETTY_FUNCTION__, pbrm->name, install, is_installed);
503
504 /*
505 * If we are installed and asked to do so again
506 * just return. If we are not installed and asked
507 * and asked to delete just return;
508 */
509 if (install && is_installed)
510 return;
511
512 if (!install && !is_installed)
513 return;
514
515 s = zclient->obuf;
516 stream_reset(s);
517
518 zclient_create_header(s,
519 install ? ZEBRA_RULE_ADD : ZEBRA_RULE_DELETE,
520 VRF_DEFAULT);
521
522 /*
523 * We are sending one item at a time at the moment
524 */
525 stream_putl(s, 1);
526
527 DEBUGD(&pbr_dbg_zebra, "%s: \t%s %s %d %s %u",
528 __PRETTY_FUNCTION__, install ? "Installing" : "Deleting",
529 pbrm->name, install, pmi->ifp->name, pmi->delete);
530
531 pbr_encode_pbr_map_sequence(s, pbrms, pmi->ifp);
532
533 stream_putw_at(s, 0, stream_get_endp(s));
534
535 zclient_send_message(zclient);
536 }