]> git.proxmox.com Git - mirror_frr.git/blob - isisd/isis_zebra.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / isisd / isis_zebra.c
1 /*
2 * IS-IS Rout(e)ing protocol - isis_zebra.c
3 *
4 * Copyright (C) 2001,2002 Sampo Saaristo
5 * Tampere University of Technology
6 * Institute of Communications Engineering
7 * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public Licenseas published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; see the file COPYING; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <zebra.h>
25
26 #include "thread.h"
27 #include "command.h"
28 #include "memory.h"
29 #include "log.h"
30 #include "if.h"
31 #include "network.h"
32 #include "prefix.h"
33 #include "zclient.h"
34 #include "stream.h"
35 #include "linklist.h"
36 #include "nexthop.h"
37 #include "vrf.h"
38 #include "libfrr.h"
39
40 #include "isisd/dict.h"
41 #include "isisd/isis_constants.h"
42 #include "isisd/isis_common.h"
43 #include "isisd/isis_flags.h"
44 #include "isisd/isis_misc.h"
45 #include "isisd/isis_circuit.h"
46 #include "isisd/isisd.h"
47 #include "isisd/isis_circuit.h"
48 #include "isisd/isis_csm.h"
49 #include "isisd/isis_lsp.h"
50 #include "isisd/isis_route.h"
51 #include "isisd/isis_zebra.h"
52 #include "isisd/isis_te.h"
53
54 struct zclient *zclient = NULL;
55
56 /* Router-id update message from zebra. */
57 static int isis_router_id_update_zebra(int command, struct zclient *zclient,
58 zebra_size_t length, vrf_id_t vrf_id)
59 {
60 struct isis_area *area;
61 struct listnode *node;
62 struct prefix router_id;
63
64 /*
65 * If ISIS TE is enable, TE Router ID is set through specific command.
66 * See mpls_te_router_addr() command in isis_te.c
67 */
68 if (IS_MPLS_TE(isisMplsTE))
69 return 0;
70
71 zebra_router_id_update_read(zclient->ibuf, &router_id);
72 if (isis->router_id == router_id.u.prefix4.s_addr)
73 return 0;
74
75 isis->router_id = router_id.u.prefix4.s_addr;
76 for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area))
77 if (listcount(area->area_addrs) > 0)
78 lsp_regenerate_schedule(area, area->is_type, 0);
79
80 return 0;
81 }
82
83 static int isis_zebra_if_add(int command, struct zclient *zclient,
84 zebra_size_t length, vrf_id_t vrf_id)
85 {
86 struct interface *ifp;
87
88 ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);
89
90 if (if_is_operative(ifp))
91 isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
92 ifp);
93
94 return 0;
95 }
96
97 static int isis_zebra_if_del(int command, struct zclient *zclient,
98 zebra_size_t length, vrf_id_t vrf_id)
99 {
100 struct interface *ifp;
101 struct stream *s;
102
103 s = zclient->ibuf;
104 ifp = zebra_interface_state_read(s, vrf_id);
105
106 if (!ifp)
107 return 0;
108
109 if (if_is_operative(ifp))
110 zlog_warn("Zebra: got delete of %s, but interface is still up",
111 ifp->name);
112
113 isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
114
115 /* Cannot call if_delete because we should retain the pseudo interface
116 in case there is configuration info attached to it. */
117 if_delete_retain(ifp);
118
119 if_set_index(ifp, IFINDEX_INTERNAL);
120
121 return 0;
122 }
123
124 static int isis_zebra_if_state_up(int command, struct zclient *zclient,
125 zebra_size_t length, vrf_id_t vrf_id)
126 {
127 struct interface *ifp;
128
129 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
130
131 if (ifp == NULL)
132 return 0;
133
134 isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
135
136 return 0;
137 }
138
139 static int isis_zebra_if_state_down(int command, struct zclient *zclient,
140 zebra_size_t length, vrf_id_t vrf_id)
141 {
142 struct interface *ifp;
143 struct isis_circuit *circuit;
144
145 ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);
146
147 if (ifp == NULL)
148 return 0;
149
150 circuit = isis_csm_state_change(IF_DOWN_FROM_Z,
151 circuit_scan_by_ifp(ifp), ifp);
152 if (circuit)
153 SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
154
155 return 0;
156 }
157
158 static int isis_zebra_if_address_add(int command, struct zclient *zclient,
159 zebra_size_t length, vrf_id_t vrf_id)
160 {
161 struct connected *c;
162 struct prefix *p;
163 char buf[PREFIX2STR_BUFFER];
164
165 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD,
166 zclient->ibuf, vrf_id);
167
168 if (c == NULL)
169 return 0;
170
171 p = c->address;
172
173 prefix2str(p, buf, sizeof(buf));
174 #ifdef EXTREME_DEBUG
175 if (p->family == AF_INET)
176 zlog_debug("connected IP address %s", buf);
177 if (p->family == AF_INET6)
178 zlog_debug("connected IPv6 address %s", buf);
179 #endif /* EXTREME_DEBUG */
180 if (if_is_operative(c->ifp))
181 isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c);
182
183 return 0;
184 }
185
186 static int isis_zebra_if_address_del(int command, struct zclient *client,
187 zebra_size_t length, vrf_id_t vrf_id)
188 {
189 struct connected *c;
190 struct interface *ifp;
191 #ifdef EXTREME_DEBUG
192 struct prefix *p;
193 char buf[PREFIX2STR_BUFFER];
194 #endif /* EXTREME_DEBUG */
195
196 c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE,
197 zclient->ibuf, vrf_id);
198
199 if (c == NULL)
200 return 0;
201
202 ifp = c->ifp;
203
204 #ifdef EXTREME_DEBUG
205 p = c->address;
206 prefix2str(p, buf, sizeof(buf));
207
208 if (p->family == AF_INET)
209 zlog_debug("disconnected IP address %s", buf);
210 if (p->family == AF_INET6)
211 zlog_debug("disconnected IPv6 address %s", buf);
212 #endif /* EXTREME_DEBUG */
213
214 if (if_is_operative(ifp))
215 isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c);
216 connected_free(c);
217
218 return 0;
219 }
220
221 static int isis_zebra_link_params(int command, struct zclient *zclient,
222 zebra_size_t length)
223 {
224 struct interface *ifp;
225
226 ifp = zebra_interface_link_params_read(zclient->ibuf);
227
228 if (ifp == NULL)
229 return 0;
230
231 /* Update TE TLV */
232 isis_mpls_te_update(ifp);
233
234 return 0;
235 }
236
237 static void isis_zebra_route_add_route(struct prefix *prefix,
238 struct prefix_ipv6 *src_p,
239 struct isis_route_info *route_info)
240 {
241 struct zapi_route api;
242 struct zapi_nexthop *api_nh;
243 struct isis_nexthop *nexthop;
244 struct isis_nexthop6 *nexthop6;
245 struct listnode *node;
246 int count = 0;
247
248 if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
249 return;
250
251 memset(&api, 0, sizeof(api));
252 if (fabricd)
253 api.flags |= ZEBRA_FLAG_ONLINK;
254 api.vrf_id = VRF_DEFAULT;
255 api.type = PROTO_TYPE;
256 api.safi = SAFI_UNICAST;
257 api.prefix = *prefix;
258 if (src_p && src_p->prefixlen) {
259 api.src_prefix = *src_p;
260 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
261 }
262 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
263 SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);
264 api.metric = route_info->cost;
265 #if 0
266 SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
267 api.distance = route_info->depth;
268 #endif
269
270 /* Nexthops */
271 switch (prefix->family) {
272 case AF_INET:
273 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node,
274 nexthop)) {
275 if (count >= MULTIPATH_NUM)
276 break;
277 api_nh = &api.nexthops[count];
278 api_nh->vrf_id = VRF_DEFAULT;
279 /* FIXME: can it be ? */
280 if (nexthop->ip.s_addr != INADDR_ANY) {
281 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
282 api_nh->gate.ipv4 = nexthop->ip;
283 } else {
284 api_nh->type = NEXTHOP_TYPE_IFINDEX;
285 }
286 api_nh->ifindex = nexthop->ifindex;
287 count++;
288 }
289 break;
290 case AF_INET6:
291 for (ALL_LIST_ELEMENTS_RO(route_info->nexthops6, node,
292 nexthop6)) {
293 if (count >= MULTIPATH_NUM)
294 break;
295 if (!IN6_IS_ADDR_LINKLOCAL(&nexthop6->ip6)
296 && !IN6_IS_ADDR_UNSPECIFIED(&nexthop6->ip6)) {
297 continue;
298 }
299
300 api_nh = &api.nexthops[count];
301 api_nh->vrf_id = VRF_DEFAULT;
302 api_nh->gate.ipv6 = nexthop6->ip6;
303 api_nh->ifindex = nexthop6->ifindex;
304 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
305 count++;
306 }
307 break;
308 }
309 if (!count)
310 return;
311
312 api.nexthop_num = count;
313
314 zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
315 SET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
316 UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
317 }
318
319 static void isis_zebra_route_del_route(struct prefix *prefix,
320 struct prefix_ipv6 *src_p,
321 struct isis_route_info *route_info)
322 {
323 struct zapi_route api;
324
325 if (!CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
326 return;
327
328 memset(&api, 0, sizeof(api));
329 api.vrf_id = VRF_DEFAULT;
330 api.type = PROTO_TYPE;
331 api.safi = SAFI_UNICAST;
332 api.prefix = *prefix;
333 if (src_p && src_p->prefixlen) {
334 api.src_prefix = *src_p;
335 SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX);
336 }
337
338 zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
339 UNSET_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
340 }
341
342 void isis_zebra_route_update(struct prefix *prefix,
343 struct prefix_ipv6 *src_p,
344 struct isis_route_info *route_info)
345 {
346 if (zclient->sock < 0)
347 return;
348
349 if (CHECK_FLAG(route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
350 isis_zebra_route_add_route(prefix, src_p, route_info);
351 else
352 isis_zebra_route_del_route(prefix, src_p, route_info);
353 }
354
355 static int isis_zebra_read(int command, struct zclient *zclient,
356 zebra_size_t length, vrf_id_t vrf_id)
357 {
358 struct zapi_route api;
359
360 if (zapi_route_decode(zclient->ibuf, &api) < 0)
361 return -1;
362
363 /*
364 * Avoid advertising a false default reachability. (A default
365 * route installed by IS-IS gets redistributed from zebra back
366 * into IS-IS causing us to start advertising default reachabity
367 * without this check)
368 */
369 if (api.prefix.prefixlen == 0
370 && api.src_prefix.prefixlen == 0
371 && api.type == PROTO_TYPE) {
372 command = ZEBRA_REDISTRIBUTE_ROUTE_DEL;
373 }
374
375 if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
376 isis_redist_add(api.type, &api.prefix, &api.src_prefix,
377 api.distance, api.metric);
378 else
379 isis_redist_delete(api.type, &api.prefix, &api.src_prefix);
380
381 return 0;
382 }
383
384 int isis_distribute_list_update(int routetype)
385 {
386 return 0;
387 }
388
389 void isis_zebra_redistribute_set(afi_t afi, int type)
390 {
391 if (type == DEFAULT_ROUTE)
392 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,
393 zclient, VRF_DEFAULT);
394 else
395 zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
396 0, VRF_DEFAULT);
397 }
398
399 void isis_zebra_redistribute_unset(afi_t afi, int type)
400 {
401 if (type == DEFAULT_ROUTE)
402 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,
403 zclient, VRF_DEFAULT);
404 else
405 zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi,
406 type, 0, VRF_DEFAULT);
407 }
408
409 static void isis_zebra_connected(struct zclient *zclient)
410 {
411 zclient_send_reg_requests(zclient, VRF_DEFAULT);
412 }
413
414 void isis_zebra_init(struct thread_master *master)
415 {
416 zclient = zclient_new(master, &zclient_options_default);
417 zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
418 zclient->zebra_connected = isis_zebra_connected;
419 zclient->router_id_update = isis_router_id_update_zebra;
420 zclient->interface_add = isis_zebra_if_add;
421 zclient->interface_delete = isis_zebra_if_del;
422 zclient->interface_up = isis_zebra_if_state_up;
423 zclient->interface_down = isis_zebra_if_state_down;
424 zclient->interface_address_add = isis_zebra_if_address_add;
425 zclient->interface_address_delete = isis_zebra_if_address_del;
426 zclient->interface_link_params = isis_zebra_link_params;
427 zclient->redistribute_route_add = isis_zebra_read;
428 zclient->redistribute_route_del = isis_zebra_read;
429
430 return;
431 }
432
433 void isis_zebra_stop(void)
434 {
435 zclient_stop(zclient);
436 zclient_free(zclient);
437 frr_fini();
438 }