]>
Commit | Line | Data |
---|---|---|
eac6e3f0 RW |
1 | /* |
2 | * Copyright (C) 2016 by Open Source Routing. | |
3 | * | |
180fc2cd RW |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
eac6e3f0 | 8 | * |
180fc2cd | 9 | * This program is distributed in the hope that it will be useful, but |
eac6e3f0 RW |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * General Public License for more details. | |
13 | * | |
180fc2cd RW |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; see the file COPYING; if not, write to the | |
16 | * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
17 | * MA 02110-1301 USA | |
eac6e3f0 RW |
18 | */ |
19 | ||
20 | #include <zebra.h> | |
21 | ||
22 | #include "prefix.h" | |
23 | #include "stream.h" | |
24 | #include "memory.h" | |
25 | #include "zclient.h" | |
26 | #include "command.h" | |
27 | #include "network.h" | |
28 | #include "linklist.h" | |
ce549947 | 29 | #include "mpls.h" |
eac6e3f0 RW |
30 | |
31 | #include "ldpd.h" | |
32 | #include "ldpe.h" | |
33 | #include "lde.h" | |
34 | #include "log.h" | |
35 | #include "ldp_debug.h" | |
36 | ||
37 | static void ifp2kif(struct interface *, struct kif *); | |
38 | static void ifc2kaddr(struct interface *, struct connected *, | |
39 | struct kaddr *); | |
bad6b0e7 | 40 | static int ldp_zebra_send_mpls_labels(int, struct kroute *); |
121f9dee QY |
41 | static int ldp_router_id_update(ZAPI_CALLBACK_ARGS); |
42 | static int ldp_interface_add(ZAPI_CALLBACK_ARGS); | |
43 | static int ldp_interface_delete(ZAPI_CALLBACK_ARGS); | |
44 | static int ldp_interface_status_change(ZAPI_CALLBACK_ARGS); | |
45 | static int ldp_interface_address_add(ZAPI_CALLBACK_ARGS); | |
46 | static int ldp_interface_address_delete(ZAPI_CALLBACK_ARGS); | |
47 | static int ldp_zebra_read_route(ZAPI_CALLBACK_ARGS); | |
48 | static int ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS); | |
eac6e3f0 RW |
49 | static void ldp_zebra_connected(struct zclient *); |
50 | ||
51 | static struct zclient *zclient; | |
52 | ||
53 | static void | |
54 | ifp2kif(struct interface *ifp, struct kif *kif) | |
55 | { | |
56 | memset(kif, 0, sizeof(*kif)); | |
57 | strlcpy(kif->ifname, ifp->name, sizeof(kif->ifname)); | |
58 | kif->ifindex = ifp->ifindex; | |
988ded8d | 59 | kif->operative = if_is_operative(ifp); |
26519d8c | 60 | if (ifp->ll_type == ZEBRA_LLT_ETHER) |
9bff8057 | 61 | memcpy(kif->mac, ifp->hw_addr, ETH_ALEN); |
eac6e3f0 RW |
62 | } |
63 | ||
64 | static void | |
65 | ifc2kaddr(struct interface *ifp, struct connected *ifc, struct kaddr *ka) | |
66 | { | |
67 | memset(ka, 0, sizeof(*ka)); | |
9cf67225 | 68 | strlcpy(ka->ifname, ifp->name, sizeof(ka->ifname)); |
eac6e3f0 RW |
69 | ka->ifindex = ifp->ifindex; |
70 | ka->af = ifc->address->family; | |
71 | ka->prefixlen = ifc->address->prefixlen; | |
72 | ||
73 | switch (ka->af) { | |
74 | case AF_INET: | |
75 | ka->addr.v4 = ifc->address->u.prefix4; | |
76 | if (ifc->destination) | |
77 | ka->dstbrd.v4 = ifc->destination->u.prefix4; | |
78 | break; | |
79 | case AF_INET6: | |
80 | ka->addr.v6 = ifc->address->u.prefix6; | |
81 | if (ifc->destination) | |
82 | ka->dstbrd.v6 = ifc->destination->u.prefix6; | |
83 | break; | |
84 | default: | |
85 | break; | |
86 | } | |
87 | } | |
88 | ||
87b5f1b7 RW |
89 | void |
90 | pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw) | |
91 | { | |
92 | memset(zpw, 0, sizeof(*zpw)); | |
93 | strlcpy(zpw->ifname, pw->ifname, sizeof(zpw->ifname)); | |
94 | zpw->ifindex = pw->ifindex; | |
95 | zpw->type = pw->l2vpn->pw_type; | |
96 | zpw->af = pw->af; | |
97 | zpw->nexthop.ipv6 = pw->addr.v6; | |
98 | zpw->local_label = NO_LABEL; | |
99 | zpw->remote_label = NO_LABEL; | |
100 | if (pw->flags & F_PW_CWORD) | |
101 | zpw->flags = F_PSEUDOWIRE_CWORD; | |
102 | zpw->data.ldp.lsr_id = pw->lsr_id; | |
103 | zpw->data.ldp.pwid = pw->pwid; | |
104 | strlcpy(zpw->data.ldp.vpn_name, pw->l2vpn->name, | |
105 | sizeof(zpw->data.ldp.vpn_name)); | |
106 | } | |
107 | ||
ce549947 | 108 | static int |
bad6b0e7 | 109 | ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr) |
ce549947 | 110 | { |
bad6b0e7 | 111 | struct zapi_labels zl = {}; |
ea6b290b | 112 | struct zapi_nexthop_label *znh; |
ce549947 RW |
113 | |
114 | if (kr->local_label < MPLS_LABEL_RESERVED_MAX || | |
115 | kr->remote_label == NO_LABEL) | |
116 | return (0); | |
117 | ||
88d88a9c | 118 | debug_zebra_out("prefix %s/%u nexthop %s ifindex %u labels %s/%s (%s)", |
ce549947 | 119 | log_addr(kr->af, &kr->prefix), kr->prefixlen, |
88d88a9c RW |
120 | log_addr(kr->af, &kr->nexthop), kr->ifindex, |
121 | log_label(kr->local_label), log_label(kr->remote_label), | |
ce549947 RW |
122 | (cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete"); |
123 | ||
bad6b0e7 | 124 | zl.type = ZEBRA_LSP_LDP; |
b3c49d0e RW |
125 | zl.local_label = kr->local_label; |
126 | ||
127 | /* Set prefix. */ | |
128 | SET_FLAG(zl.message, ZAPI_LABELS_FTN); | |
129 | zl.route.prefix.family = kr->af; | |
ce549947 RW |
130 | switch (kr->af) { |
131 | case AF_INET: | |
b3c49d0e | 132 | zl.route.prefix.u.prefix4 = kr->prefix.v4; |
ce549947 RW |
133 | break; |
134 | case AF_INET6: | |
b3c49d0e | 135 | zl.route.prefix.u.prefix6 = kr->prefix.v6; |
ce549947 RW |
136 | break; |
137 | default: | |
b3c49d0e | 138 | fatalx("ldp_zebra_send_mpls_labels: unknown af"); |
ce549947 | 139 | } |
b3c49d0e RW |
140 | zl.route.prefix.prefixlen = kr->prefixlen; |
141 | zl.route.type = kr->route_type; | |
142 | zl.route.instance = kr->route_instance; | |
143 | ||
144 | /* Set nexthop. */ | |
ea6b290b RW |
145 | zl.nexthop_num = 1; |
146 | znh = &zl.nexthops[0]; | |
b3c49d0e RW |
147 | switch (kr->af) { |
148 | case AF_INET: | |
ea6b290b RW |
149 | znh->family = AF_INET; |
150 | znh->address.ipv4 = kr->nexthop.v4; | |
b3c49d0e | 151 | if (kr->ifindex) |
ea6b290b | 152 | znh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
b3c49d0e | 153 | else |
ea6b290b | 154 | znh->type = NEXTHOP_TYPE_IPV4; |
b3c49d0e RW |
155 | break; |
156 | case AF_INET6: | |
ea6b290b RW |
157 | znh->family = AF_INET6; |
158 | znh->address.ipv6 = kr->nexthop.v6; | |
b3c49d0e | 159 | if (kr->ifindex) |
ea6b290b | 160 | znh->type = NEXTHOP_TYPE_IPV6_IFINDEX; |
b3c49d0e | 161 | else |
ea6b290b | 162 | znh->type = NEXTHOP_TYPE_IPV6; |
b3c49d0e RW |
163 | break; |
164 | default: | |
165 | break; | |
166 | } | |
ea6b290b RW |
167 | znh->ifindex = kr->ifindex; |
168 | znh->label = kr->remote_label; | |
ce549947 | 169 | |
bad6b0e7 | 170 | return zebra_send_mpls_labels(zclient, cmd, &zl); |
ce549947 RW |
171 | } |
172 | ||
eac6e3f0 RW |
173 | int |
174 | kr_change(struct kroute *kr) | |
175 | { | |
bad6b0e7 | 176 | return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr)); |
eac6e3f0 RW |
177 | } |
178 | ||
179 | int | |
180 | kr_delete(struct kroute *kr) | |
181 | { | |
bad6b0e7 | 182 | return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr)); |
eac6e3f0 RW |
183 | } |
184 | ||
185 | int | |
87b5f1b7 | 186 | kmpw_add(struct zapi_pw *zpw) |
eac6e3f0 | 187 | { |
87b5f1b7 RW |
188 | debug_zebra_out("pseudowire %s nexthop %s (add)", |
189 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
190 | ||
191 | return (zebra_send_pw(zclient, ZEBRA_PW_ADD, zpw)); | |
eac6e3f0 RW |
192 | } |
193 | ||
194 | int | |
87b5f1b7 | 195 | kmpw_del(struct zapi_pw *zpw) |
eac6e3f0 | 196 | { |
87b5f1b7 RW |
197 | debug_zebra_out("pseudowire %s nexthop %s (del)", |
198 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
199 | ||
200 | return (zebra_send_pw(zclient, ZEBRA_PW_DELETE, zpw)); | |
201 | } | |
202 | ||
203 | int | |
204 | kmpw_set(struct zapi_pw *zpw) | |
205 | { | |
206 | debug_zebra_out("pseudowire %s nexthop %s labels %u/%u (set)", | |
207 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop), | |
208 | zpw->local_label, zpw->remote_label); | |
209 | ||
210 | return (zebra_send_pw(zclient, ZEBRA_PW_SET, zpw)); | |
211 | } | |
212 | ||
213 | int | |
214 | kmpw_unset(struct zapi_pw *zpw) | |
215 | { | |
216 | debug_zebra_out("pseudowire %s nexthop %s (unset)", | |
217 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
218 | ||
219 | return (zebra_send_pw(zclient, ZEBRA_PW_UNSET, zpw)); | |
eac6e3f0 RW |
220 | } |
221 | ||
222 | void | |
223 | kif_redistribute(const char *ifname) | |
224 | { | |
f4e14fdb RW |
225 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
226 | struct listnode *cnode; | |
eac6e3f0 RW |
227 | struct interface *ifp; |
228 | struct connected *ifc; | |
229 | struct kif kif; | |
230 | struct kaddr ka; | |
231 | ||
451fda4f | 232 | FOR_ALL_INTERFACES (vrf, ifp) { |
eac6e3f0 RW |
233 | if (ifname && strcmp(ifname, ifp->name) != 0) |
234 | continue; | |
235 | ||
236 | ifp2kif(ifp, &kif); | |
52b530fc | 237 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 RW |
238 | |
239 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { | |
240 | ifc2kaddr(ifp, ifc, &ka); | |
241 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, | |
242 | sizeof(ka)); | |
243 | } | |
244 | } | |
245 | } | |
246 | ||
247 | static int | |
121f9dee | 248 | ldp_router_id_update(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
249 | { |
250 | struct prefix router_id; | |
251 | ||
252 | zebra_router_id_update_read(zclient->ibuf, &router_id); | |
253 | ||
254 | if (bad_addr_v4(router_id.u.prefix4)) | |
255 | return (0); | |
256 | ||
257 | debug_zebra_in("router-id update %s", inet_ntoa(router_id.u.prefix4)); | |
258 | ||
259 | global.rtr_id.s_addr = router_id.u.prefix4.s_addr; | |
260 | main_imsg_compose_ldpe(IMSG_RTRID_UPDATE, 0, &global.rtr_id, | |
261 | sizeof(global.rtr_id)); | |
262 | ||
263 | return (0); | |
264 | } | |
265 | ||
266 | static int | |
121f9dee | 267 | ldp_interface_add(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
268 | { |
269 | struct interface *ifp; | |
270 | struct kif kif; | |
271 | ||
272 | ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); | |
273 | debug_zebra_in("interface add %s index %d mtu %d", ifp->name, | |
274 | ifp->ifindex, ifp->mtu); | |
275 | ||
276 | ifp2kif(ifp, &kif); | |
52b530fc | 277 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 RW |
278 | |
279 | return (0); | |
280 | } | |
281 | ||
282 | static int | |
121f9dee | 283 | ldp_interface_delete(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
284 | { |
285 | struct interface *ifp; | |
9cf67225 | 286 | struct kif kif; |
eac6e3f0 RW |
287 | |
288 | /* zebra_interface_state_read() updates interface structure in iflist */ | |
289 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); | |
290 | if (ifp == NULL) | |
291 | return (0); | |
292 | ||
293 | debug_zebra_in("interface delete %s index %d mtu %d", ifp->name, | |
294 | ifp->ifindex, ifp->mtu); | |
295 | ||
296 | /* To support pseudo interface do not free interface structure. */ | |
297 | /* if_delete(ifp); */ | |
ff880b78 | 298 | if_set_index(ifp, IFINDEX_INTERNAL); |
9cf67225 RW |
299 | |
300 | ifp2kif(ifp, &kif); | |
301 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); | |
eac6e3f0 RW |
302 | |
303 | return (0); | |
304 | } | |
305 | ||
306 | static int | |
121f9dee | 307 | ldp_interface_status_change(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
308 | { |
309 | struct interface *ifp; | |
310 | struct listnode *node; | |
311 | struct connected *ifc; | |
312 | struct kif kif; | |
313 | struct kaddr ka; | |
eac6e3f0 RW |
314 | |
315 | /* | |
316 | * zebra_interface_state_read() updates interface structure in | |
317 | * iflist. | |
318 | */ | |
319 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); | |
320 | if (ifp == NULL) | |
321 | return (0); | |
322 | ||
323 | debug_zebra_in("interface %s state update", ifp->name); | |
324 | ||
325 | ifp2kif(ifp, &kif); | |
52b530fc | 326 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 | 327 | |
988ded8d | 328 | if (if_is_operative(ifp)) { |
eac6e3f0 RW |
329 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { |
330 | ifc2kaddr(ifp, ifc, &ka); | |
331 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, | |
332 | sizeof(ka)); | |
333 | } | |
334 | } else { | |
335 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { | |
336 | ifc2kaddr(ifp, ifc, &ka); | |
337 | main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, | |
338 | sizeof(ka)); | |
339 | } | |
340 | } | |
341 | ||
342 | return (0); | |
343 | } | |
344 | ||
345 | static int | |
121f9dee | 346 | ldp_interface_address_add(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
347 | { |
348 | struct connected *ifc; | |
349 | struct interface *ifp; | |
350 | struct kaddr ka; | |
351 | ||
121f9dee | 352 | ifc = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
eac6e3f0 RW |
353 | if (ifc == NULL) |
354 | return (0); | |
355 | ||
356 | ifp = ifc->ifp; | |
357 | ifc2kaddr(ifp, ifc, &ka); | |
358 | ||
359 | /* Filter invalid addresses. */ | |
360 | if (bad_addr(ka.af, &ka.addr)) | |
361 | return (0); | |
362 | ||
9cf67225 RW |
363 | debug_zebra_in("address add %s/%u interface %s", |
364 | log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name); | |
eac6e3f0 RW |
365 | |
366 | /* notify ldpe about new address */ | |
367 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, sizeof(ka)); | |
368 | ||
369 | return (0); | |
370 | } | |
371 | ||
372 | static int | |
121f9dee | 373 | ldp_interface_address_delete(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
374 | { |
375 | struct connected *ifc; | |
376 | struct interface *ifp; | |
377 | struct kaddr ka; | |
378 | ||
121f9dee | 379 | ifc = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
eac6e3f0 RW |
380 | if (ifc == NULL) |
381 | return (0); | |
382 | ||
383 | ifp = ifc->ifp; | |
384 | ifc2kaddr(ifp, ifc, &ka); | |
385 | connected_free(ifc); | |
386 | ||
387 | /* Filter invalid addresses. */ | |
388 | if (bad_addr(ka.af, &ka.addr)) | |
389 | return (0); | |
390 | ||
9cf67225 RW |
391 | debug_zebra_in("address delete %s/%u interface %s", |
392 | log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name); | |
eac6e3f0 RW |
393 | |
394 | /* notify ldpe about removed address */ | |
395 | main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, sizeof(ka)); | |
396 | ||
397 | return (0); | |
398 | } | |
399 | ||
400 | static int | |
121f9dee | 401 | ldp_zebra_read_route(ZAPI_CALLBACK_ARGS) |
eac6e3f0 | 402 | { |
74489921 RW |
403 | struct zapi_route api; |
404 | struct zapi_nexthop *api_nh; | |
eac6e3f0 | 405 | struct kroute kr; |
74489921 RW |
406 | int i, add = 0; |
407 | ||
408 | if (zapi_route_decode(zclient->ibuf, &api) < 0) | |
409 | return -1; | |
410 | ||
411 | /* we completely ignore srcdest routes for now. */ | |
412 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) | |
413 | return (0); | |
eac6e3f0 RW |
414 | |
415 | memset(&kr, 0, sizeof(kr)); | |
74489921 RW |
416 | kr.af = api.prefix.family; |
417 | switch (kr.af) { | |
418 | case AF_INET: | |
419 | kr.prefix.v4 = api.prefix.u.prefix4; | |
420 | break; | |
421 | case AF_INET6: | |
422 | kr.prefix.v6 = api.prefix.u.prefix6; | |
423 | break; | |
424 | default: | |
425 | break; | |
426 | } | |
427 | kr.prefixlen = api.prefix.prefixlen; | |
e132dea0 RW |
428 | kr.route_type = api.type; |
429 | kr.route_instance = api.instance; | |
eac6e3f0 | 430 | |
74489921 | 431 | switch (api.type) { |
a695cc7b | 432 | case ZEBRA_ROUTE_CONNECT: |
eac6e3f0 | 433 | kr.flags |= F_CONNECTED; |
a695cc7b RW |
434 | break; |
435 | case ZEBRA_ROUTE_BGP: | |
436 | /* LDP should follow the IGP and ignore BGP routes */ | |
437 | return (0); | |
438 | default: | |
439 | break; | |
440 | } | |
441 | ||
eac6e3f0 RW |
442 | if (bad_addr(kr.af, &kr.prefix) || |
443 | (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6))) | |
444 | return (0); | |
445 | ||
121f9dee | 446 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) |
1f2ff5b5 RW |
447 | add = 1; |
448 | ||
74489921 | 449 | if (api.nexthop_num == 0) |
1f2ff5b5 RW |
450 | debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", |
451 | log_addr(kr.af, &kr.prefix), kr.prefixlen, | |
74489921 | 452 | zebra_route_string(api.type)); |
eac6e3f0 RW |
453 | |
454 | /* loop through all the nexthops */ | |
74489921 RW |
455 | for (i = 0; i < api.nexthop_num; i++) { |
456 | api_nh = &api.nexthops[i]; | |
cddef813 RW |
457 | switch (api_nh->type) { |
458 | case NEXTHOP_TYPE_IPV4: | |
459 | if (kr.af != AF_INET) | |
460 | continue; | |
461 | kr.nexthop.v4 = api_nh->gate.ipv4; | |
462 | kr.ifindex = 0; | |
463 | break; | |
464 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
465 | if (kr.af != AF_INET) | |
466 | continue; | |
74489921 | 467 | kr.nexthop.v4 = api_nh->gate.ipv4; |
cddef813 | 468 | kr.ifindex = api_nh->ifindex; |
eac6e3f0 | 469 | break; |
cddef813 RW |
470 | case NEXTHOP_TYPE_IPV6: |
471 | if (kr.af != AF_INET6) | |
472 | continue; | |
74489921 | 473 | kr.nexthop.v6 = api_nh->gate.ipv6; |
cddef813 | 474 | kr.ifindex = 0; |
eac6e3f0 | 475 | break; |
cddef813 RW |
476 | case NEXTHOP_TYPE_IPV6_IFINDEX: |
477 | if (kr.af != AF_INET6) | |
478 | continue; | |
479 | kr.nexthop.v6 = api_nh->gate.ipv6; | |
480 | kr.ifindex = api_nh->ifindex; | |
481 | break; | |
482 | case NEXTHOP_TYPE_IFINDEX: | |
483 | if (!(kr.flags & F_CONNECTED)) | |
484 | continue; | |
eac6e3f0 | 485 | break; |
cddef813 RW |
486 | default: |
487 | continue; | |
eac6e3f0 | 488 | } |
eac6e3f0 | 489 | |
1f2ff5b5 RW |
490 | debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", |
491 | (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), | |
492 | kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, | |
74489921 | 493 | zebra_route_string(api.type)); |
1f2ff5b5 RW |
494 | |
495 | if (add) | |
eac6e3f0 RW |
496 | main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, |
497 | sizeof(kr)); | |
eac6e3f0 RW |
498 | } |
499 | ||
8cb1fc45 | 500 | main_imsg_compose_lde(IMSG_NETWORK_UPDATE, 0, &kr, sizeof(kr)); |
134970a2 | 501 | |
eac6e3f0 RW |
502 | return (0); |
503 | } | |
504 | ||
87b5f1b7 RW |
505 | /* |
506 | * Receive PW status update from Zebra and send it to LDE process. | |
507 | */ | |
508 | static int | |
121f9dee | 509 | ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS) |
87b5f1b7 RW |
510 | { |
511 | struct zapi_pw_status zpw; | |
512 | ||
121f9dee | 513 | zebra_read_pw_status_update(cmd, zclient, length, vrf_id, &zpw); |
87b5f1b7 RW |
514 | |
515 | debug_zebra_in("pseudowire %s status %s", zpw.ifname, | |
516 | (zpw.status == PW_STATUS_UP) ? "up" : "down"); | |
517 | ||
518 | main_imsg_compose_lde(IMSG_PW_UPDATE, 0, &zpw, sizeof(zpw)); | |
519 | ||
520 | return (0); | |
521 | } | |
522 | ||
eac6e3f0 RW |
523 | static void |
524 | ldp_zebra_connected(struct zclient *zclient) | |
525 | { | |
eac6e3f0 | 526 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
a695cc7b RW |
527 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, |
528 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); | |
529 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, | |
530 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); | |
eac6e3f0 RW |
531 | } |
532 | ||
342213ea DS |
533 | extern struct zebra_privs_t ldpd_privs; |
534 | ||
eac6e3f0 RW |
535 | void |
536 | ldp_zebra_init(struct thread_master *master) | |
537 | { | |
538 | /* Set default values. */ | |
26f63a1e | 539 | zclient = zclient_new(master, &zclient_options_default); |
342213ea | 540 | zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs); |
eac6e3f0 RW |
541 | |
542 | /* set callbacks */ | |
543 | zclient->zebra_connected = ldp_zebra_connected; | |
544 | zclient->router_id_update = ldp_router_id_update; | |
545 | zclient->interface_add = ldp_interface_add; | |
546 | zclient->interface_delete = ldp_interface_delete; | |
547 | zclient->interface_up = ldp_interface_status_change; | |
548 | zclient->interface_down = ldp_interface_status_change; | |
549 | zclient->interface_address_add = ldp_interface_address_add; | |
550 | zclient->interface_address_delete = ldp_interface_address_delete; | |
74489921 RW |
551 | zclient->redistribute_route_add = ldp_zebra_read_route; |
552 | zclient->redistribute_route_del = ldp_zebra_read_route; | |
87b5f1b7 | 553 | zclient->pw_status_update = ldp_zebra_read_pw_status_update; |
eac6e3f0 | 554 | } |
64dffe25 RW |
555 | |
556 | void | |
557 | ldp_zebra_destroy(void) | |
558 | { | |
559 | zclient_stop(zclient); | |
560 | zclient_free(zclient); | |
561 | zclient = NULL; | |
562 | } |