3 * Copyright (C) 2018 Cumulus Networks, Inc.
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
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.
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"
38 #include "static_vrf.h"
39 #include "static_routes.h"
40 #include "static_zebra.h"
41 #include "static_nht.h"
42 #include "static_vty.h"
44 /* Zebra structure to hold current status. */
45 struct zclient
*zclient
;
47 static struct interface
*zebra_interface_if_lookup(struct stream
*s
)
49 char ifname_tmp
[INTERFACE_NAMSIZ
];
51 /* Read interface name. */
52 stream_get(ifname_tmp
, s
, INTERFACE_NAMSIZ
);
55 return if_lookup_by_name(ifname_tmp
, VRF_DEFAULT
);
58 /* Inteface addition message from zebra. */
59 static int interface_add(int command
, struct zclient
*zclient
,
60 zebra_size_t length
, vrf_id_t vrf_id
)
62 struct interface
*ifp
;
64 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
69 static_ifindex_update(ifp
, true);
73 static int interface_delete(int command
, struct zclient
*zclient
,
74 zebra_size_t length
, vrf_id_t vrf_id
)
76 struct interface
*ifp
;
80 /* zebra_interface_state_read () updates interface structure in iflist
82 ifp
= zebra_interface_state_read(s
, vrf_id
);
87 if_set_index(ifp
, IFINDEX_INTERNAL
);
89 static_ifindex_update(ifp
, false);
93 static int interface_address_add(int command
, struct zclient
*zclient
,
94 zebra_size_t length
, vrf_id_t vrf_id
)
96 zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
101 static int interface_address_delete(int command
, struct zclient
*zclient
,
102 zebra_size_t length
, vrf_id_t vrf_id
)
106 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
115 static int interface_state_up(int command
, struct zclient
*zclient
,
116 zebra_size_t length
, vrf_id_t vrf_id
)
118 struct interface
*ifp
;
120 ifp
= zebra_interface_if_lookup(zclient
->ibuf
);
122 if (if_is_vrf(ifp
)) {
123 struct static_vrf
*svrf
= static_vrf_lookup_by_id(vrf_id
);
125 static_fixup_vrf_ids(svrf
);
126 static_config_install_delayed_routes(svrf
);
132 static int interface_state_down(int command
, struct zclient
*zclient
,
133 zebra_size_t length
, vrf_id_t vrf_id
)
135 zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
140 static int route_notify_owner(int command
, struct zclient
*zclient
,
141 zebra_size_t length
, vrf_id_t vrf_id
)
144 enum zapi_route_notify_owner note
;
146 char buf
[PREFIX_STRLEN
];
148 prefix2str(&p
, buf
, sizeof(buf
));
150 if (!zapi_route_notify_decode(zclient
->ibuf
, &p
, &table_id
, ¬e
))
154 case ZAPI_ROUTE_FAIL_INSTALL
:
155 zlog_warn("%s: Route %s failed to install for table: %u",
156 __PRETTY_FUNCTION__
, buf
, table_id
);
158 case ZAPI_ROUTE_BETTER_ADMIN_WON
:
159 zlog_warn("%s: Route %s over-ridden by better route for table: %u",
160 __PRETTY_FUNCTION__
, buf
, table_id
);
162 case ZAPI_ROUTE_INSTALLED
:
164 case ZAPI_ROUTE_REMOVED
:
166 case ZAPI_ROUTE_REMOVE_FAIL
:
167 zlog_warn("%s: Route %s failure to remove for table: %u",
168 __PRETTY_FUNCTION__
, buf
, table_id
);
174 static void zebra_connected(struct zclient
*zclient
)
176 zclient_send_reg_requests(zclient
, VRF_DEFAULT
);
180 static int static_zebra_nexthop_update(int command
, struct zclient
*zclient
,
181 zebra_size_t length
, vrf_id_t vrf_id
)
183 struct zapi_route nhr
;
186 if (!zapi_nexthop_update_decode(zclient
->ibuf
, &nhr
)) {
187 zlog_warn("Failure to decode nexthop update message");
191 if (nhr
.prefix
.family
== AF_INET6
)
194 static_nht_update(&nhr
.prefix
, nhr
.nexthop_num
, afi
, vrf_id
);
198 static void static_zebra_capabilities(struct zclient_capabilities
*cap
)
200 mpls_enabled
= cap
->mpls_enabled
;
203 void static_zebra_nht_register(struct static_route
*si
, bool reg
)
209 ZEBRA_NEXTHOP_REGISTER
: ZEBRA_NEXTHOP_UNREGISTER
;
211 if (si
->nh_registered
&& reg
)
214 if (!si
->nh_registered
&& !reg
)
217 memset(&p
, 0, sizeof(p
));
219 case STATIC_IPV4_GATEWAY_IFNAME
:
221 case STATIC_BLACKHOLE
:
222 case STATIC_IPV6_GATEWAY_IFNAME
:
224 case STATIC_IPV4_GATEWAY
:
226 p
.prefixlen
= IPV4_MAX_BITLEN
;
227 p
.u
.prefix4
= si
->addr
.ipv4
;
229 case STATIC_IPV6_GATEWAY
:
231 p
.prefixlen
= IPV6_MAX_BITLEN
;
232 p
.u
.prefix6
= si
->addr
.ipv6
;
236 if (zclient_send_rnh(zclient
, cmd
, &p
, false, si
->nh_vrf_id
) < 0)
237 zlog_warn("%s: Failure to send nexthop to zebra",
238 __PRETTY_FUNCTION__
);
240 si
->nh_registered
= reg
;
243 extern void static_zebra_route_add(struct route_node
*rn
, vrf_id_t vrf_id
,
244 safi_t safi
, bool install
)
246 struct static_route
*si
= rn
->info
;
247 const struct prefix
*p
, *src_pp
;
248 struct zapi_nexthop
*api_nh
;
249 struct zapi_route api
;
253 srcdest_rnode_prefixes(rn
, &p
, &src_pp
);
255 memset(&api
, 0, sizeof(api
));
257 api
.type
= ZEBRA_ROUTE_STATIC
;
259 memcpy(&api
.prefix
, p
, sizeof(api
.prefix
));
262 SET_FLAG(api
.message
, ZAPI_MESSAGE_SRCPFX
);
263 memcpy(&api
.src_prefix
, src_pp
, sizeof(api
.src_prefix
));
266 SET_FLAG(api
.message
, ZAPI_MESSAGE_NEXTHOP
);
268 for (/*loaded above*/; si
; si
= si
->next
) {
269 api_nh
= &api
.nexthops
[nh_num
];
270 if (si
->nh_vrf_id
== VRF_UNKNOWN
)
274 * If we create a ecmp static route the
275 * last distance and tag entered wins. Why because
276 * this cli choosen sucks
279 SET_FLAG(api
.message
, ZAPI_MESSAGE_DISTANCE
);
280 api
.distance
= si
->distance
;
283 SET_FLAG(api
.message
, ZAPI_MESSAGE_TAG
);
287 api
.tableid
= si
->table_id
;
289 api_nh
->vrf_id
= si
->nh_vrf_id
;
292 if (si
->ifindex
== IFINDEX_INTERNAL
)
294 api_nh
->ifindex
= si
->ifindex
;
295 api_nh
->type
= NEXTHOP_TYPE_IFINDEX
;
297 case STATIC_IPV4_GATEWAY
:
300 api_nh
->type
= NEXTHOP_TYPE_IPV4
;
301 api_nh
->gate
= si
->addr
;
303 case STATIC_IPV4_GATEWAY_IFNAME
:
304 if (si
->ifindex
== IFINDEX_INTERNAL
)
306 api_nh
->ifindex
= si
->ifindex
;
307 api_nh
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
308 api_nh
->gate
= si
->addr
;
310 case STATIC_IPV6_GATEWAY
:
313 api_nh
->type
= NEXTHOP_TYPE_IPV6
;
314 api_nh
->gate
= si
->addr
;
316 case STATIC_IPV6_GATEWAY_IFNAME
:
317 if (si
->ifindex
== IFINDEX_INTERNAL
)
319 api_nh
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
320 api_nh
->ifindex
= si
->ifindex
;
321 api_nh
->gate
= si
->addr
;
323 case STATIC_BLACKHOLE
:
324 api_nh
->type
= NEXTHOP_TYPE_BLACKHOLE
;
325 switch (si
->bh_type
) {
326 case STATIC_BLACKHOLE_DROP
:
327 case STATIC_BLACKHOLE_NULL
:
328 api_nh
->bh_type
= BLACKHOLE_NULL
;
330 case STATIC_BLACKHOLE_REJECT
:
331 api_nh
->bh_type
= BLACKHOLE_REJECT
;
336 if (si
->snh_label
.num_labels
) {
339 SET_FLAG(api
.message
, ZAPI_MESSAGE_LABEL
);
340 api_nh
->label_num
= si
->snh_label
.num_labels
;
341 for (i
= 0; i
< api_nh
->label_num
; i
++)
342 api_nh
->labels
[i
] = si
->snh_label
.label
[i
];
347 api
.nexthop_num
= nh_num
;
350 * If we have been given an install but nothing is valid
351 * go ahead and delete the route for double plus fun
353 if (!nh_num
&& install
)
356 zclient_route_send(install
?
357 ZEBRA_ROUTE_ADD
: ZEBRA_ROUTE_DELETE
,
360 void static_zebra_init(void)
362 struct zclient_options opt
= { .receive_notify
= true };
364 zclient
= zclient_new_notify(master
, &opt
);
366 zclient_init(zclient
, ZEBRA_ROUTE_STATIC
, 0, &static_privs
);
367 zclient
->zebra_capabilities
= static_zebra_capabilities
;
368 zclient
->zebra_connected
= zebra_connected
;
369 zclient
->interface_add
= interface_add
;
370 zclient
->interface_delete
= interface_delete
;
371 zclient
->interface_up
= interface_state_up
;
372 zclient
->interface_down
= interface_state_down
;
373 zclient
->interface_address_add
= interface_address_add
;
374 zclient
->interface_address_delete
= interface_address_delete
;
375 zclient
->route_notify_owner
= route_notify_owner
;
376 zclient
->nexthop_update
= static_zebra_nexthop_update
;