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