]>
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 | 41 | static int ldp_router_id_update(ZAPI_CALLBACK_ARGS); |
121f9dee QY |
42 | static int ldp_interface_address_add(ZAPI_CALLBACK_ARGS); |
43 | static int ldp_interface_address_delete(ZAPI_CALLBACK_ARGS); | |
44 | static int ldp_zebra_read_route(ZAPI_CALLBACK_ARGS); | |
45 | static int ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS); | |
eac6e3f0 | 46 | static void ldp_zebra_connected(struct zclient *); |
2d1aa1e8 | 47 | static void ldp_zebra_filter_update(struct access_list *access); |
eac6e3f0 RW |
48 | |
49 | static struct zclient *zclient; | |
50 | ||
51 | static void | |
52 | ifp2kif(struct interface *ifp, struct kif *kif) | |
53 | { | |
54 | memset(kif, 0, sizeof(*kif)); | |
55 | strlcpy(kif->ifname, ifp->name, sizeof(kif->ifname)); | |
56 | kif->ifindex = ifp->ifindex; | |
988ded8d | 57 | kif->operative = if_is_operative(ifp); |
26519d8c | 58 | if (ifp->ll_type == ZEBRA_LLT_ETHER) |
9bff8057 | 59 | memcpy(kif->mac, ifp->hw_addr, ETH_ALEN); |
eac6e3f0 RW |
60 | } |
61 | ||
62 | static void | |
63 | ifc2kaddr(struct interface *ifp, struct connected *ifc, struct kaddr *ka) | |
64 | { | |
65 | memset(ka, 0, sizeof(*ka)); | |
9cf67225 | 66 | strlcpy(ka->ifname, ifp->name, sizeof(ka->ifname)); |
eac6e3f0 RW |
67 | ka->ifindex = ifp->ifindex; |
68 | ka->af = ifc->address->family; | |
69 | ka->prefixlen = ifc->address->prefixlen; | |
70 | ||
71 | switch (ka->af) { | |
72 | case AF_INET: | |
73 | ka->addr.v4 = ifc->address->u.prefix4; | |
74 | if (ifc->destination) | |
75 | ka->dstbrd.v4 = ifc->destination->u.prefix4; | |
76 | break; | |
77 | case AF_INET6: | |
78 | ka->addr.v6 = ifc->address->u.prefix6; | |
79 | if (ifc->destination) | |
80 | ka->dstbrd.v6 = ifc->destination->u.prefix6; | |
81 | break; | |
82 | default: | |
83 | break; | |
84 | } | |
85 | } | |
86 | ||
87b5f1b7 RW |
87 | void |
88 | pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw) | |
89 | { | |
90 | memset(zpw, 0, sizeof(*zpw)); | |
91 | strlcpy(zpw->ifname, pw->ifname, sizeof(zpw->ifname)); | |
92 | zpw->ifindex = pw->ifindex; | |
93 | zpw->type = pw->l2vpn->pw_type; | |
94 | zpw->af = pw->af; | |
95 | zpw->nexthop.ipv6 = pw->addr.v6; | |
96 | zpw->local_label = NO_LABEL; | |
97 | zpw->remote_label = NO_LABEL; | |
98 | if (pw->flags & F_PW_CWORD) | |
99 | zpw->flags = F_PSEUDOWIRE_CWORD; | |
100 | zpw->data.ldp.lsr_id = pw->lsr_id; | |
101 | zpw->data.ldp.pwid = pw->pwid; | |
102 | strlcpy(zpw->data.ldp.vpn_name, pw->l2vpn->name, | |
103 | sizeof(zpw->data.ldp.vpn_name)); | |
104 | } | |
105 | ||
ce549947 | 106 | static int |
bad6b0e7 | 107 | ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr) |
ce549947 | 108 | { |
bad6b0e7 | 109 | struct zapi_labels zl = {}; |
4945002d | 110 | struct zapi_nexthop *znh; |
ce549947 | 111 | |
8963e0c8 | 112 | if (kr->local_label < MPLS_LABEL_RESERVED_MAX) |
ce549947 RW |
113 | return (0); |
114 | ||
88d88a9c | 115 | debug_zebra_out("prefix %s/%u nexthop %s ifindex %u labels %s/%s (%s)", |
ce549947 | 116 | log_addr(kr->af, &kr->prefix), kr->prefixlen, |
88d88a9c RW |
117 | log_addr(kr->af, &kr->nexthop), kr->ifindex, |
118 | log_label(kr->local_label), log_label(kr->remote_label), | |
ce549947 RW |
119 | (cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete"); |
120 | ||
bad6b0e7 | 121 | zl.type = ZEBRA_LSP_LDP; |
b3c49d0e RW |
122 | zl.local_label = kr->local_label; |
123 | ||
124 | /* Set prefix. */ | |
8963e0c8 RW |
125 | if (kr->remote_label != NO_LABEL) { |
126 | SET_FLAG(zl.message, ZAPI_LABELS_FTN); | |
127 | zl.route.prefix.family = kr->af; | |
128 | switch (kr->af) { | |
129 | case AF_INET: | |
130 | zl.route.prefix.u.prefix4 = kr->prefix.v4; | |
131 | break; | |
132 | case AF_INET6: | |
133 | zl.route.prefix.u.prefix6 = kr->prefix.v6; | |
134 | break; | |
135 | default: | |
136 | fatalx("ldp_zebra_send_mpls_labels: unknown af"); | |
137 | } | |
138 | zl.route.prefix.prefixlen = kr->prefixlen; | |
139 | zl.route.type = kr->route_type; | |
140 | zl.route.instance = kr->route_instance; | |
ce549947 | 141 | } |
8963e0c8 RW |
142 | |
143 | /* | |
144 | * For broken LSPs, instruct the forwarding plane to pop the top-level | |
145 | * label and forward packets normally. This is a best-effort attempt | |
146 | * to deliver labeled IP packets to their final destination (instead of | |
147 | * dropping them). | |
148 | */ | |
149 | if (kr->remote_label == NO_LABEL) | |
150 | kr->remote_label = MPLS_LABEL_IMPLICIT_NULL; | |
b3c49d0e RW |
151 | |
152 | /* Set nexthop. */ | |
ea6b290b RW |
153 | zl.nexthop_num = 1; |
154 | znh = &zl.nexthops[0]; | |
b3c49d0e RW |
155 | switch (kr->af) { |
156 | case AF_INET: | |
4945002d | 157 | znh->gate.ipv4 = kr->nexthop.v4; |
b3c49d0e | 158 | if (kr->ifindex) |
ea6b290b | 159 | znh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
b3c49d0e | 160 | else |
ea6b290b | 161 | znh->type = NEXTHOP_TYPE_IPV4; |
b3c49d0e RW |
162 | break; |
163 | case AF_INET6: | |
4945002d | 164 | znh->gate.ipv6 = kr->nexthop.v6; |
b3c49d0e | 165 | if (kr->ifindex) |
ea6b290b | 166 | znh->type = NEXTHOP_TYPE_IPV6_IFINDEX; |
b3c49d0e | 167 | else |
ea6b290b | 168 | znh->type = NEXTHOP_TYPE_IPV6; |
b3c49d0e RW |
169 | break; |
170 | default: | |
171 | break; | |
172 | } | |
ea6b290b | 173 | znh->ifindex = kr->ifindex; |
4945002d MS |
174 | znh->label_num = 1; |
175 | znh->labels[0] = kr->remote_label; | |
ce549947 | 176 | |
bad6b0e7 | 177 | return zebra_send_mpls_labels(zclient, cmd, &zl); |
ce549947 RW |
178 | } |
179 | ||
eac6e3f0 RW |
180 | int |
181 | kr_change(struct kroute *kr) | |
182 | { | |
bad6b0e7 | 183 | return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr)); |
eac6e3f0 RW |
184 | } |
185 | ||
186 | int | |
187 | kr_delete(struct kroute *kr) | |
188 | { | |
bad6b0e7 | 189 | return (ldp_zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr)); |
eac6e3f0 RW |
190 | } |
191 | ||
192 | int | |
87b5f1b7 | 193 | kmpw_add(struct zapi_pw *zpw) |
eac6e3f0 | 194 | { |
87b5f1b7 RW |
195 | debug_zebra_out("pseudowire %s nexthop %s (add)", |
196 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
197 | ||
198 | return (zebra_send_pw(zclient, ZEBRA_PW_ADD, zpw)); | |
eac6e3f0 RW |
199 | } |
200 | ||
201 | int | |
87b5f1b7 | 202 | kmpw_del(struct zapi_pw *zpw) |
eac6e3f0 | 203 | { |
87b5f1b7 RW |
204 | debug_zebra_out("pseudowire %s nexthop %s (del)", |
205 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
206 | ||
207 | return (zebra_send_pw(zclient, ZEBRA_PW_DELETE, zpw)); | |
208 | } | |
209 | ||
210 | int | |
211 | kmpw_set(struct zapi_pw *zpw) | |
212 | { | |
213 | debug_zebra_out("pseudowire %s nexthop %s labels %u/%u (set)", | |
214 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop), | |
215 | zpw->local_label, zpw->remote_label); | |
216 | ||
217 | return (zebra_send_pw(zclient, ZEBRA_PW_SET, zpw)); | |
218 | } | |
219 | ||
220 | int | |
221 | kmpw_unset(struct zapi_pw *zpw) | |
222 | { | |
223 | debug_zebra_out("pseudowire %s nexthop %s (unset)", | |
224 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
225 | ||
226 | return (zebra_send_pw(zclient, ZEBRA_PW_UNSET, zpw)); | |
eac6e3f0 RW |
227 | } |
228 | ||
229 | void | |
230 | kif_redistribute(const char *ifname) | |
231 | { | |
f4e14fdb RW |
232 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
233 | struct listnode *cnode; | |
eac6e3f0 RW |
234 | struct interface *ifp; |
235 | struct connected *ifc; | |
236 | struct kif kif; | |
237 | struct kaddr ka; | |
238 | ||
451fda4f | 239 | FOR_ALL_INTERFACES (vrf, ifp) { |
eac6e3f0 RW |
240 | if (ifname && strcmp(ifname, ifp->name) != 0) |
241 | continue; | |
242 | ||
243 | ifp2kif(ifp, &kif); | |
52b530fc | 244 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 RW |
245 | |
246 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { | |
247 | ifc2kaddr(ifp, ifc, &ka); | |
248 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, | |
249 | sizeof(ka)); | |
250 | } | |
251 | } | |
252 | } | |
253 | ||
254 | static int | |
121f9dee | 255 | ldp_router_id_update(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
256 | { |
257 | struct prefix router_id; | |
258 | ||
259 | zebra_router_id_update_read(zclient->ibuf, &router_id); | |
260 | ||
261 | if (bad_addr_v4(router_id.u.prefix4)) | |
262 | return (0); | |
263 | ||
264 | debug_zebra_in("router-id update %s", inet_ntoa(router_id.u.prefix4)); | |
265 | ||
266 | global.rtr_id.s_addr = router_id.u.prefix4.s_addr; | |
267 | main_imsg_compose_ldpe(IMSG_RTRID_UPDATE, 0, &global.rtr_id, | |
268 | sizeof(global.rtr_id)); | |
269 | ||
270 | return (0); | |
271 | } | |
272 | ||
273 | static int | |
ef7bd2a3 | 274 | ldp_ifp_create(struct interface *ifp) |
eac6e3f0 | 275 | { |
eac6e3f0 RW |
276 | struct kif kif; |
277 | ||
eac6e3f0 RW |
278 | debug_zebra_in("interface add %s index %d mtu %d", ifp->name, |
279 | ifp->ifindex, ifp->mtu); | |
280 | ||
281 | ifp2kif(ifp, &kif); | |
52b530fc | 282 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 | 283 | |
ef7bd2a3 | 284 | return 0; |
eac6e3f0 RW |
285 | } |
286 | ||
287 | static int | |
3c3c3252 | 288 | ldp_ifp_destroy(struct interface *ifp) |
eac6e3f0 | 289 | { |
9cf67225 | 290 | struct kif kif; |
eac6e3f0 | 291 | |
eac6e3f0 RW |
292 | debug_zebra_in("interface delete %s index %d mtu %d", ifp->name, |
293 | ifp->ifindex, ifp->mtu); | |
294 | ||
9cf67225 RW |
295 | ifp2kif(ifp, &kif); |
296 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); | |
eac6e3f0 RW |
297 | |
298 | return (0); | |
299 | } | |
300 | ||
301 | static int | |
ddbf3e60 | 302 | ldp_interface_status_change_helper(struct interface *ifp) |
eac6e3f0 | 303 | { |
eac6e3f0 RW |
304 | struct listnode *node; |
305 | struct connected *ifc; | |
306 | struct kif kif; | |
307 | struct kaddr ka; | |
eac6e3f0 | 308 | |
eac6e3f0 RW |
309 | debug_zebra_in("interface %s state update", ifp->name); |
310 | ||
311 | ifp2kif(ifp, &kif); | |
52b530fc | 312 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 | 313 | |
988ded8d | 314 | if (if_is_operative(ifp)) { |
eac6e3f0 RW |
315 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { |
316 | ifc2kaddr(ifp, ifc, &ka); | |
317 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, | |
318 | sizeof(ka)); | |
319 | } | |
320 | } else { | |
321 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { | |
322 | ifc2kaddr(ifp, ifc, &ka); | |
323 | main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, | |
324 | sizeof(ka)); | |
325 | } | |
326 | } | |
327 | ||
328 | return (0); | |
329 | } | |
ddbf3e60 | 330 | |
b0b69e59 DS |
331 | static int ldp_ifp_up(struct interface *ifp) |
332 | { | |
333 | return ldp_interface_status_change_helper(ifp); | |
334 | } | |
ddbf3e60 | 335 | |
b0b69e59 DS |
336 | static int ldp_ifp_down(struct interface *ifp) |
337 | { | |
ddbf3e60 DS |
338 | return ldp_interface_status_change_helper(ifp); |
339 | } | |
eac6e3f0 RW |
340 | |
341 | static int | |
121f9dee | 342 | ldp_interface_address_add(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
343 | { |
344 | struct connected *ifc; | |
345 | struct interface *ifp; | |
346 | struct kaddr ka; | |
347 | ||
121f9dee | 348 | ifc = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
eac6e3f0 RW |
349 | if (ifc == NULL) |
350 | return (0); | |
351 | ||
352 | ifp = ifc->ifp; | |
353 | ifc2kaddr(ifp, ifc, &ka); | |
354 | ||
355 | /* Filter invalid addresses. */ | |
356 | if (bad_addr(ka.af, &ka.addr)) | |
357 | return (0); | |
358 | ||
9cf67225 RW |
359 | debug_zebra_in("address add %s/%u interface %s", |
360 | log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name); | |
eac6e3f0 RW |
361 | |
362 | /* notify ldpe about new address */ | |
363 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, sizeof(ka)); | |
364 | ||
365 | return (0); | |
366 | } | |
367 | ||
368 | static int | |
121f9dee | 369 | ldp_interface_address_delete(ZAPI_CALLBACK_ARGS) |
eac6e3f0 RW |
370 | { |
371 | struct connected *ifc; | |
372 | struct interface *ifp; | |
373 | struct kaddr ka; | |
374 | ||
121f9dee | 375 | ifc = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
eac6e3f0 RW |
376 | if (ifc == NULL) |
377 | return (0); | |
378 | ||
379 | ifp = ifc->ifp; | |
380 | ifc2kaddr(ifp, ifc, &ka); | |
721c0857 | 381 | connected_free(&ifc); |
eac6e3f0 RW |
382 | |
383 | /* Filter invalid addresses. */ | |
384 | if (bad_addr(ka.af, &ka.addr)) | |
385 | return (0); | |
386 | ||
9cf67225 RW |
387 | debug_zebra_in("address delete %s/%u interface %s", |
388 | log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name); | |
eac6e3f0 RW |
389 | |
390 | /* notify ldpe about removed address */ | |
391 | main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, sizeof(ka)); | |
392 | ||
393 | return (0); | |
394 | } | |
395 | ||
396 | static int | |
121f9dee | 397 | ldp_zebra_read_route(ZAPI_CALLBACK_ARGS) |
eac6e3f0 | 398 | { |
74489921 RW |
399 | struct zapi_route api; |
400 | struct zapi_nexthop *api_nh; | |
eac6e3f0 | 401 | struct kroute kr; |
74489921 RW |
402 | int i, add = 0; |
403 | ||
404 | if (zapi_route_decode(zclient->ibuf, &api) < 0) | |
405 | return -1; | |
406 | ||
407 | /* we completely ignore srcdest routes for now. */ | |
408 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) | |
409 | return (0); | |
eac6e3f0 RW |
410 | |
411 | memset(&kr, 0, sizeof(kr)); | |
74489921 RW |
412 | kr.af = api.prefix.family; |
413 | switch (kr.af) { | |
414 | case AF_INET: | |
415 | kr.prefix.v4 = api.prefix.u.prefix4; | |
416 | break; | |
417 | case AF_INET6: | |
418 | kr.prefix.v6 = api.prefix.u.prefix6; | |
419 | break; | |
420 | default: | |
421 | break; | |
422 | } | |
423 | kr.prefixlen = api.prefix.prefixlen; | |
e132dea0 RW |
424 | kr.route_type = api.type; |
425 | kr.route_instance = api.instance; | |
eac6e3f0 | 426 | |
74489921 | 427 | switch (api.type) { |
a695cc7b | 428 | case ZEBRA_ROUTE_CONNECT: |
eac6e3f0 | 429 | kr.flags |= F_CONNECTED; |
a695cc7b RW |
430 | break; |
431 | case ZEBRA_ROUTE_BGP: | |
432 | /* LDP should follow the IGP and ignore BGP routes */ | |
433 | return (0); | |
434 | default: | |
435 | break; | |
436 | } | |
437 | ||
eac6e3f0 RW |
438 | if (bad_addr(kr.af, &kr.prefix) || |
439 | (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6))) | |
440 | return (0); | |
441 | ||
121f9dee | 442 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) |
1f2ff5b5 RW |
443 | add = 1; |
444 | ||
74489921 | 445 | if (api.nexthop_num == 0) |
1f2ff5b5 RW |
446 | debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", |
447 | log_addr(kr.af, &kr.prefix), kr.prefixlen, | |
74489921 | 448 | zebra_route_string(api.type)); |
eac6e3f0 RW |
449 | |
450 | /* loop through all the nexthops */ | |
74489921 RW |
451 | for (i = 0; i < api.nexthop_num; i++) { |
452 | api_nh = &api.nexthops[i]; | |
cddef813 RW |
453 | switch (api_nh->type) { |
454 | case NEXTHOP_TYPE_IPV4: | |
455 | if (kr.af != AF_INET) | |
456 | continue; | |
457 | kr.nexthop.v4 = api_nh->gate.ipv4; | |
458 | kr.ifindex = 0; | |
459 | break; | |
460 | case NEXTHOP_TYPE_IPV4_IFINDEX: | |
461 | if (kr.af != AF_INET) | |
462 | continue; | |
74489921 | 463 | kr.nexthop.v4 = api_nh->gate.ipv4; |
cddef813 | 464 | kr.ifindex = api_nh->ifindex; |
eac6e3f0 | 465 | break; |
cddef813 RW |
466 | case NEXTHOP_TYPE_IPV6: |
467 | if (kr.af != AF_INET6) | |
468 | continue; | |
74489921 | 469 | kr.nexthop.v6 = api_nh->gate.ipv6; |
cddef813 | 470 | kr.ifindex = 0; |
eac6e3f0 | 471 | break; |
cddef813 RW |
472 | case NEXTHOP_TYPE_IPV6_IFINDEX: |
473 | if (kr.af != AF_INET6) | |
474 | continue; | |
475 | kr.nexthop.v6 = api_nh->gate.ipv6; | |
476 | kr.ifindex = api_nh->ifindex; | |
477 | break; | |
478 | case NEXTHOP_TYPE_IFINDEX: | |
479 | if (!(kr.flags & F_CONNECTED)) | |
480 | continue; | |
eac6e3f0 | 481 | break; |
cddef813 RW |
482 | default: |
483 | continue; | |
eac6e3f0 | 484 | } |
eac6e3f0 | 485 | |
1f2ff5b5 RW |
486 | debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", |
487 | (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), | |
488 | kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, | |
74489921 | 489 | zebra_route_string(api.type)); |
1f2ff5b5 RW |
490 | |
491 | if (add) | |
eac6e3f0 RW |
492 | main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, |
493 | sizeof(kr)); | |
eac6e3f0 RW |
494 | } |
495 | ||
8cb1fc45 | 496 | main_imsg_compose_lde(IMSG_NETWORK_UPDATE, 0, &kr, sizeof(kr)); |
134970a2 | 497 | |
eac6e3f0 RW |
498 | return (0); |
499 | } | |
500 | ||
87b5f1b7 RW |
501 | /* |
502 | * Receive PW status update from Zebra and send it to LDE process. | |
503 | */ | |
504 | static int | |
121f9dee | 505 | ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS) |
87b5f1b7 RW |
506 | { |
507 | struct zapi_pw_status zpw; | |
508 | ||
121f9dee | 509 | zebra_read_pw_status_update(cmd, zclient, length, vrf_id, &zpw); |
87b5f1b7 RW |
510 | |
511 | debug_zebra_in("pseudowire %s status %s", zpw.ifname, | |
512 | (zpw.status == PW_STATUS_UP) ? "up" : "down"); | |
513 | ||
514 | main_imsg_compose_lde(IMSG_PW_UPDATE, 0, &zpw, sizeof(zpw)); | |
515 | ||
516 | return (0); | |
517 | } | |
518 | ||
eac6e3f0 RW |
519 | static void |
520 | ldp_zebra_connected(struct zclient *zclient) | |
521 | { | |
eac6e3f0 | 522 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
a695cc7b RW |
523 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, |
524 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); | |
525 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, | |
526 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); | |
eac6e3f0 RW |
527 | } |
528 | ||
2d1aa1e8 | 529 | static void |
530 | ldp_zebra_filter_update(struct access_list *access) | |
531 | { | |
532 | struct ldp_access laccess; | |
533 | ||
534 | if (access && access->name[0] != '\0') { | |
535 | strlcpy(laccess.name, access->name, sizeof(laccess.name)); | |
536 | laccess.type = access->type; | |
537 | debug_evt("%s ACL update filter name %s type %d", __func__, | |
538 | access->name, access->type); | |
539 | ||
540 | main_imsg_compose_both(IMSG_FILTER_UPDATE, &laccess, | |
541 | sizeof(laccess)); | |
542 | } | |
543 | } | |
544 | ||
342213ea DS |
545 | extern struct zebra_privs_t ldpd_privs; |
546 | ||
eac6e3f0 RW |
547 | void |
548 | ldp_zebra_init(struct thread_master *master) | |
549 | { | |
138c5a74 DS |
550 | if_zapi_callbacks(ldp_ifp_create, ldp_ifp_up, |
551 | ldp_ifp_down, ldp_ifp_destroy); | |
552 | ||
eac6e3f0 | 553 | /* Set default values. */ |
26f63a1e | 554 | zclient = zclient_new(master, &zclient_options_default); |
342213ea | 555 | zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs); |
eac6e3f0 RW |
556 | |
557 | /* set callbacks */ | |
558 | zclient->zebra_connected = ldp_zebra_connected; | |
559 | zclient->router_id_update = ldp_router_id_update; | |
eac6e3f0 RW |
560 | zclient->interface_address_add = ldp_interface_address_add; |
561 | zclient->interface_address_delete = ldp_interface_address_delete; | |
74489921 RW |
562 | zclient->redistribute_route_add = ldp_zebra_read_route; |
563 | zclient->redistribute_route_del = ldp_zebra_read_route; | |
87b5f1b7 | 564 | zclient->pw_status_update = ldp_zebra_read_pw_status_update; |
2d1aa1e8 | 565 | |
566 | /* Access list initialize. */ | |
567 | access_list_add_hook(ldp_zebra_filter_update); | |
568 | access_list_delete_hook(ldp_zebra_filter_update); | |
eac6e3f0 | 569 | } |
64dffe25 RW |
570 | |
571 | void | |
572 | ldp_zebra_destroy(void) | |
573 | { | |
574 | zclient_stop(zclient); | |
575 | zclient_free(zclient); | |
576 | zclient = NULL; | |
577 | } |