3 * Copyright (C) 2018 Cumulus Networks, Inc.
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
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
28 #include "srcdest_table.h"
36 #include "nexthop_group.h"
40 #include "static_vrf.h"
41 #include "static_routes.h"
42 #include "static_zebra.h"
43 #include "static_nht.h"
44 #include "static_vty.h"
48 /* Zebra structure to hold current status. */
49 struct zclient
*zclient
;
50 static struct hash
*static_nht_hash
;
52 static struct interface
*zebra_interface_if_lookup(struct stream
*s
)
54 char ifname_tmp
[INTERFACE_NAMSIZ
];
56 /* Read interface name. */
57 stream_get(ifname_tmp
, s
, INTERFACE_NAMSIZ
);
60 return if_lookup_by_name(ifname_tmp
, VRF_DEFAULT
);
63 /* Inteface addition message from zebra. */
64 static int static_ifp_create(struct interface
*ifp
)
66 static_ifindex_update(ifp
, true);
71 static int interface_delete(ZAPI_CALLBACK_ARGS
)
73 struct interface
*ifp
;
77 /* zebra_interface_state_read () updates interface structure in iflist
79 ifp
= zebra_interface_state_read(s
, vrf_id
);
84 if_set_index(ifp
, IFINDEX_INTERNAL
);
86 static_ifindex_update(ifp
, false);
90 static int interface_address_add(ZAPI_CALLBACK_ARGS
)
92 zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
97 static int interface_address_delete(ZAPI_CALLBACK_ARGS
)
101 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
110 static int interface_state_up(ZAPI_CALLBACK_ARGS
)
112 struct interface
*ifp
;
114 ifp
= zebra_interface_if_lookup(zclient
->ibuf
);
117 if (if_is_vrf(ifp
)) {
118 struct static_vrf
*svrf
=
119 static_vrf_lookup_by_id(vrf_id
);
121 static_fixup_vrf_ids(svrf
);
122 static_config_install_delayed_routes(svrf
);
125 /* Install any static reliant on this interface coming up */
126 static_install_intf_nh(ifp
);
127 static_ifindex_update(ifp
, true);
133 static int interface_state_down(ZAPI_CALLBACK_ARGS
)
135 struct interface
*ifp
;
137 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
140 static_ifindex_update(ifp
, false);
145 static int route_notify_owner(ZAPI_CALLBACK_ARGS
)
148 enum zapi_route_notify_owner note
;
150 char buf
[PREFIX_STRLEN
];
152 if (!zapi_route_notify_decode(zclient
->ibuf
, &p
, &table_id
, ¬e
))
155 prefix2str(&p
, buf
, sizeof(buf
));
158 case ZAPI_ROUTE_FAIL_INSTALL
:
159 static_nht_mark_state(&p
, vrf_id
, STATIC_NOT_INSTALLED
);
160 zlog_warn("%s: Route %s failed to install for table: %u",
161 __PRETTY_FUNCTION__
, buf
, table_id
);
163 case ZAPI_ROUTE_BETTER_ADMIN_WON
:
164 static_nht_mark_state(&p
, vrf_id
, STATIC_NOT_INSTALLED
);
165 zlog_warn("%s: Route %s over-ridden by better route for table: %u",
166 __PRETTY_FUNCTION__
, buf
, table_id
);
168 case ZAPI_ROUTE_INSTALLED
:
169 static_nht_mark_state(&p
, vrf_id
, STATIC_INSTALLED
);
171 case ZAPI_ROUTE_REMOVED
:
172 static_nht_mark_state(&p
, vrf_id
, STATIC_NOT_INSTALLED
);
174 case ZAPI_ROUTE_REMOVE_FAIL
:
175 static_nht_mark_state(&p
, vrf_id
, STATIC_INSTALLED
);
176 zlog_warn("%s: Route %s failure to remove for table: %u",
177 __PRETTY_FUNCTION__
, buf
, table_id
);
183 static void zebra_connected(struct zclient
*zclient
)
185 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
188 struct static_nht_data
{
197 /* API to check whether the configured nexthop address is
198 * one of its local connected address or not.
201 static_nexthop_is_local(vrf_id_t vrfid
, struct prefix
*addr
, int family
)
203 if (family
== AF_INET
) {
204 if (if_lookup_exact_address(&addr
->u
.prefix4
,
208 } else if (family
== AF_INET6
) {
209 if (if_lookup_exact_address(&addr
->u
.prefix6
,
216 static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS
)
218 struct static_nht_data
*nhtd
, lookup
;
219 struct zapi_route nhr
;
222 if (!zapi_nexthop_update_decode(zclient
->ibuf
, &nhr
)) {
223 zlog_warn("Failure to decode nexthop update message");
227 if (nhr
.prefix
.family
== AF_INET6
)
230 if (nhr
.type
== ZEBRA_ROUTE_CONNECT
) {
231 if (static_nexthop_is_local(vrf_id
, &nhr
.prefix
,
236 memset(&lookup
, 0, sizeof(lookup
));
237 lookup
.nh
= &nhr
.prefix
;
238 lookup
.nh_vrf_id
= vrf_id
;
240 nhtd
= hash_lookup(static_nht_hash
, &lookup
);
243 nhtd
->nh_num
= nhr
.nexthop_num
;
245 static_nht_reset_start(&nhr
.prefix
, afi
, nhtd
->nh_vrf_id
);
246 static_nht_update(NULL
, &nhr
.prefix
, nhr
.nexthop_num
, afi
,
249 zlog_err("No nhtd?");
254 static void static_zebra_capabilities(struct zclient_capabilities
*cap
)
256 mpls_enabled
= cap
->mpls_enabled
;
259 static unsigned int static_nht_hash_key(const void *data
)
261 const struct static_nht_data
*nhtd
= data
;
262 unsigned int key
= 0;
264 key
= prefix_hash_key(nhtd
->nh
);
265 return jhash_1word(nhtd
->nh_vrf_id
, key
);
268 static bool static_nht_hash_cmp(const void *d1
, const void *d2
)
270 const struct static_nht_data
*nhtd1
= d1
;
271 const struct static_nht_data
*nhtd2
= d2
;
273 if (nhtd1
->nh_vrf_id
!= nhtd2
->nh_vrf_id
)
276 return prefix_same(nhtd1
->nh
, nhtd2
->nh
);
279 static void *static_nht_hash_alloc(void *data
)
281 struct static_nht_data
*copy
= data
;
282 struct static_nht_data
*new;
284 new = XMALLOC(MTYPE_TMP
, sizeof(*new));
286 new->nh
= prefix_new();
287 prefix_copy(new->nh
, copy
->nh
);
290 new->nh_vrf_id
= copy
->nh_vrf_id
;
295 static void static_nht_hash_free(void *data
)
297 struct static_nht_data
*nhtd
= data
;
299 prefix_free(nhtd
->nh
);
300 XFREE(MTYPE_TMP
, nhtd
);
303 void static_zebra_nht_register(struct route_node
*rn
,
304 struct static_route
*si
, bool reg
)
306 struct static_nht_data
*nhtd
, lookup
;
312 ZEBRA_NEXTHOP_REGISTER
: ZEBRA_NEXTHOP_UNREGISTER
;
314 if (si
->nh_registered
&& reg
)
317 if (!si
->nh_registered
&& !reg
)
320 memset(&p
, 0, sizeof(p
));
323 case STATIC_BLACKHOLE
:
325 case STATIC_IPV4_GATEWAY
:
326 case STATIC_IPV4_GATEWAY_IFNAME
:
328 p
.prefixlen
= IPV4_MAX_BITLEN
;
329 p
.u
.prefix4
= si
->addr
.ipv4
;
332 case STATIC_IPV6_GATEWAY
:
333 case STATIC_IPV6_GATEWAY_IFNAME
:
335 p
.prefixlen
= IPV6_MAX_BITLEN
;
336 p
.u
.prefix6
= si
->addr
.ipv6
;
341 memset(&lookup
, 0, sizeof(lookup
));
343 lookup
.nh_vrf_id
= si
->nh_vrf_id
;
345 si
->nh_registered
= reg
;
348 nhtd
= hash_get(static_nht_hash
, &lookup
,
349 static_nht_hash_alloc
);
353 zlog_debug("Registered nexthop(%pFX) for %pRN %d", &p
,
355 if (nhtd
->refcount
> 1 && nhtd
->nh_num
) {
356 static_nht_update(&rn
->p
, nhtd
->nh
, nhtd
->nh_num
,
361 nhtd
= hash_lookup(static_nht_hash
, &lookup
);
366 if (nhtd
->refcount
>= 1)
369 hash_release(static_nht_hash
, nhtd
);
370 static_nht_hash_free(nhtd
);
373 if (zclient_send_rnh(zclient
, cmd
, &p
, false, si
->nh_vrf_id
) < 0)
374 zlog_warn("%s: Failure to send nexthop to zebra",
375 __PRETTY_FUNCTION__
);
378 extern void static_zebra_route_add(struct route_node
*rn
,
379 struct static_route
*si_changed
,
380 vrf_id_t vrf_id
, safi_t safi
, bool install
)
382 struct static_route
*si
= rn
->info
;
383 const struct prefix
*p
, *src_pp
;
384 struct zapi_nexthop
*api_nh
;
385 struct zapi_route api
;
389 srcdest_rnode_prefixes(rn
, &p
, &src_pp
);
391 memset(&api
, 0, sizeof(api
));
393 api
.type
= ZEBRA_ROUTE_STATIC
;
395 memcpy(&api
.prefix
, p
, sizeof(api
.prefix
));
398 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
399 memcpy(&api
.src_prefix
, src_pp
, sizeof(api
.src_prefix
));
401 SET_FLAG(api
.flags
, ZEBRA_FLAG_RR_USE_DISTANCE
);
402 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
403 if (si_changed
->distance
) {
404 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
405 api
.distance
= si_changed
->distance
;
407 if (si_changed
->tag
) {
408 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
409 api
.tag
= si_changed
->tag
;
411 if (si_changed
->table_id
!= 0) {
412 SET_FLAG(api
.message
, ZAPI_MESSAGE_TABLEID
);
413 api
.tableid
= si_changed
->table_id
;
415 for (/*loaded above*/; si
; si
= si
->next
) {
416 api_nh
= &api
.nexthops
[nh_num
];
417 if (si
->nh_vrf_id
== VRF_UNKNOWN
)
420 if (si
->distance
!= si_changed
->distance
)
423 if (si
->table_id
!= si_changed
->table_id
)
426 api_nh
->vrf_id
= si
->nh_vrf_id
;
427 api_nh
->onlink
= si
->onlink
;
429 si
->state
= STATIC_SENT_TO_ZEBRA
;
433 if (si
->ifindex
== IFINDEX_INTERNAL
)
435 api_nh
->ifindex
= si
->ifindex
;
436 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
438 case STATIC_IPV4_GATEWAY
:
441 api_nh
->type
= NEXTHOP_TYPE_IPV4
;
442 api_nh
->gate
= si
->addr
;
444 case STATIC_IPV4_GATEWAY_IFNAME
:
445 if (si
->ifindex
== IFINDEX_INTERNAL
)
447 api_nh
->ifindex
= si
->ifindex
;
448 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
449 api_nh
->gate
= si
->addr
;
451 case STATIC_IPV6_GATEWAY
:
454 api_nh
->type
= NEXTHOP_TYPE_IPV6
;
455 api_nh
->gate
= si
->addr
;
457 case STATIC_IPV6_GATEWAY_IFNAME
:
458 if (si
->ifindex
== IFINDEX_INTERNAL
)
460 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
461 api_nh
->ifindex
= si
->ifindex
;
462 api_nh
->gate
= si
->addr
;
464 case STATIC_BLACKHOLE
:
465 api_nh
->type
= NEXTHOP_TYPE_BLACKHOLE
;
466 switch (si
->bh_type
) {
467 case STATIC_BLACKHOLE_DROP
:
468 case STATIC_BLACKHOLE_NULL
:
469 api_nh
->bh_type
= BLACKHOLE_NULL
;
471 case STATIC_BLACKHOLE_REJECT
:
472 api_nh
->bh_type
= BLACKHOLE_REJECT
;
477 if (si
->snh_label
.num_labels
) {
480 SET_FLAG(api
.message
, ZAPI_MESSAGE_LABEL
);
481 api_nh
->label_num
= si
->snh_label
.num_labels
;
482 for (i
= 0; i
< api_nh
->label_num
; i
++)
483 api_nh
->labels
[i
] = si
->snh_label
.label
[i
];
488 api
.nexthop_num
= nh_num
;
491 * If we have been given an install but nothing is valid
492 * go ahead and delete the route for double plus fun
494 if (!nh_num
&& install
)
497 zclient_route_send(install
?
498 ZEBRA_ROUTE_ADD
: ZEBRA_ROUTE_DELETE
,
502 static int static_ifp_up(struct interface
*ifp
)
507 static int static_ifp_down(struct interface
*ifp
)
512 static int static_ifp_destroy(struct interface
*ifp
)
517 void static_zebra_init(void)
519 struct zclient_options opt
= { .receive_notify
= true };
521 if_zapi_callbacks(static_ifp_create
, static_ifp_up
,
522 static_ifp_down
, static_ifp_destroy
);
524 zclient
= zclient_new(master
, &opt
);
526 zclient_init(zclient
, ZEBRA_ROUTE_STATIC
, 0, &static_privs
);
527 zclient
->zebra_capabilities
= static_zebra_capabilities
;
528 zclient
->zebra_connected
= zebra_connected
;
529 zclient
->interface_delete
= interface_delete
;
530 zclient
->interface_up
= interface_state_up
;
531 zclient
->interface_down
= interface_state_down
;
532 zclient
->interface_address_add
= interface_address_add
;
533 zclient
->interface_address_delete
= interface_address_delete
;
534 zclient
->route_notify_owner
= route_notify_owner
;
535 zclient
->nexthop_update
= static_zebra_nexthop_update
;
537 static_nht_hash
= hash_create(static_nht_hash_key
,
539 "Static Nexthop Tracking hash");