]>
Commit | Line | Data |
---|---|---|
eb5d44eb | 1 | /* |
d62a17ae | 2 | * IS-IS Rout(e)ing protocol - isis_zebra.c |
eb5d44eb | 3 | * |
4 | * Copyright (C) 2001,2002 Sampo Saaristo | |
d62a17ae | 5 | * Tampere University of Technology |
eb5d44eb | 6 | * Institute of Communications Engineering |
f3ccedaa | 7 | * Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org> |
eb5d44eb | 8 | * |
d62a17ae | 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) | |
eb5d44eb | 12 | * any later version. |
13 | * | |
d62a17ae | 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 | |
eb5d44eb | 17 | * more details. |
896014f4 DL |
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 | |
eb5d44eb | 22 | */ |
23 | ||
24 | #include <zebra.h> | |
eb5d44eb | 25 | |
26 | #include "thread.h" | |
27 | #include "command.h" | |
28 | #include "memory.h" | |
29 | #include "log.h" | |
363be4dd | 30 | #include "lib_errors.h" |
eb5d44eb | 31 | #include "if.h" |
32 | #include "network.h" | |
33 | #include "prefix.h" | |
34 | #include "zclient.h" | |
35 | #include "stream.h" | |
36 | #include "linklist.h" | |
f3ccedaa | 37 | #include "nexthop.h" |
7076bb2f | 38 | #include "vrf.h" |
8879bd22 | 39 | #include "libfrr.h" |
eb5d44eb | 40 | |
41 | #include "isisd/isis_constants.h" | |
42 | #include "isisd/isis_common.h" | |
3f045a08 JB |
43 | #include "isisd/isis_flags.h" |
44 | #include "isisd/isis_misc.h" | |
45 | #include "isisd/isis_circuit.h" | |
c89c05dd | 46 | #include "isisd/isisd.h" |
eb5d44eb | 47 | #include "isisd/isis_circuit.h" |
48 | #include "isisd/isis_csm.h" | |
3f045a08 | 49 | #include "isisd/isis_lsp.h" |
eb5d44eb | 50 | #include "isisd/isis_route.h" |
51 | #include "isisd/isis_zebra.h" | |
f8c06e2c | 52 | #include "isisd/isis_te.h" |
eb5d44eb | 53 | |
54 | struct zclient *zclient = NULL; | |
55 | ||
18a6dce6 | 56 | /* Router-id update message from zebra. */ |
121f9dee | 57 | static int isis_router_id_update_zebra(ZAPI_CALLBACK_ARGS) |
18a6dce6 | 58 | { |
d62a17ae | 59 | struct isis_area *area; |
60 | struct listnode *node; | |
61 | struct prefix router_id; | |
62 | ||
d62a17ae | 63 | zebra_router_id_update_read(zclient->ibuf, &router_id); |
64 | if (isis->router_id == router_id.u.prefix4.s_addr) | |
65 | return 0; | |
66 | ||
67 | isis->router_id = router_id.u.prefix4.s_addr; | |
68 | for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) | |
69 | if (listcount(area->area_addrs) > 0) | |
70 | lsp_regenerate_schedule(area, area->is_type, 0); | |
71 | ||
72 | return 0; | |
18a6dce6 | 73 | } |
eb5d44eb | 74 | |
121f9dee | 75 | static int isis_zebra_if_address_add(ZAPI_CALLBACK_ARGS) |
eb5d44eb | 76 | { |
d62a17ae | 77 | struct connected *c; |
78 | struct prefix *p; | |
79 | char buf[PREFIX2STR_BUFFER]; | |
eb5d44eb | 80 | |
d62a17ae | 81 | c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, |
82 | zclient->ibuf, vrf_id); | |
f390d2c7 | 83 | |
d62a17ae | 84 | if (c == NULL) |
85 | return 0; | |
f390d2c7 | 86 | |
d62a17ae | 87 | p = c->address; |
f390d2c7 | 88 | |
d62a17ae | 89 | prefix2str(p, buf, sizeof(buf)); |
eb5d44eb | 90 | #ifdef EXTREME_DEBUG |
d62a17ae | 91 | if (p->family == AF_INET) |
92 | zlog_debug("connected IP address %s", buf); | |
93 | if (p->family == AF_INET6) | |
94 | zlog_debug("connected IPv6 address %s", buf); | |
eb5d44eb | 95 | #endif /* EXTREME_DEBUG */ |
d62a17ae | 96 | if (if_is_operative(c->ifp)) |
97 | isis_circuit_add_addr(circuit_scan_by_ifp(c->ifp), c); | |
eb5d44eb | 98 | |
d62a17ae | 99 | return 0; |
eb5d44eb | 100 | } |
101 | ||
121f9dee | 102 | static int isis_zebra_if_address_del(ZAPI_CALLBACK_ARGS) |
eb5d44eb | 103 | { |
d62a17ae | 104 | struct connected *c; |
105 | struct interface *ifp; | |
1cd80845 | 106 | #ifdef EXTREME_DEBUG |
d62a17ae | 107 | struct prefix *p; |
108 | char buf[PREFIX2STR_BUFFER]; | |
1cd80845 | 109 | #endif /* EXTREME_DEBUG */ |
eb5d44eb | 110 | |
d62a17ae | 111 | c = zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, |
112 | zclient->ibuf, vrf_id); | |
f390d2c7 | 113 | |
d62a17ae | 114 | if (c == NULL) |
115 | return 0; | |
f390d2c7 | 116 | |
d62a17ae | 117 | ifp = c->ifp; |
f390d2c7 | 118 | |
f891f443 | 119 | #ifdef EXTREME_DEBUG |
d62a17ae | 120 | p = c->address; |
121 | prefix2str(p, buf, sizeof(buf)); | |
f891f443 | 122 | |
d62a17ae | 123 | if (p->family == AF_INET) |
124 | zlog_debug("disconnected IP address %s", buf); | |
125 | if (p->family == AF_INET6) | |
126 | zlog_debug("disconnected IPv6 address %s", buf); | |
f891f443 | 127 | #endif /* EXTREME_DEBUG */ |
f390d2c7 | 128 | |
d62a17ae | 129 | if (if_is_operative(ifp)) |
130 | isis_circuit_del_addr(circuit_scan_by_ifp(ifp), c); | |
721c0857 | 131 | connected_free(&c); |
f390d2c7 | 132 | |
d62a17ae | 133 | return 0; |
eb5d44eb | 134 | } |
135 | ||
121f9dee | 136 | static int isis_zebra_link_params(ZAPI_CALLBACK_ARGS) |
f8c06e2c | 137 | { |
d62a17ae | 138 | struct interface *ifp; |
f8c06e2c | 139 | |
edc12762 | 140 | ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id); |
f8c06e2c | 141 | |
d62a17ae | 142 | if (ifp == NULL) |
143 | return 0; | |
f8c06e2c | 144 | |
d62a17ae | 145 | /* Update TE TLV */ |
146 | isis_mpls_te_update(ifp); | |
f8c06e2c | 147 | |
d62a17ae | 148 | return 0; |
f8c06e2c OD |
149 | } |
150 | ||
0a5f3f4f RW |
151 | void isis_zebra_route_add_route(struct prefix *prefix, |
152 | struct prefix_ipv6 *src_p, | |
153 | struct isis_route_info *route_info) | |
eb5d44eb | 154 | { |
c0721de4 RW |
155 | struct zapi_route api; |
156 | struct zapi_nexthop *api_nh; | |
d62a17ae | 157 | struct isis_nexthop *nexthop; |
158 | struct listnode *node; | |
c0721de4 | 159 | int count = 0; |
d62a17ae | 160 | |
0a5f3f4f | 161 | if (zclient->sock < 0) |
d62a17ae | 162 | return; |
163 | ||
c0721de4 RW |
164 | memset(&api, 0, sizeof(api)); |
165 | api.vrf_id = VRF_DEFAULT; | |
7c0cbd0e | 166 | api.type = PROTO_TYPE; |
c0721de4 RW |
167 | api.safi = SAFI_UNICAST; |
168 | api.prefix = *prefix; | |
321c1bbb CF |
169 | if (src_p && src_p->prefixlen) { |
170 | api.src_prefix = *src_p; | |
171 | SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); | |
172 | } | |
c0721de4 RW |
173 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); |
174 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); | |
175 | api.metric = route_info->cost; | |
2097cd8a | 176 | #if 0 |
c0721de4 RW |
177 | SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); |
178 | api.distance = route_info->depth; | |
2097cd8a | 179 | #endif |
f390d2c7 | 180 | |
f80dd32b | 181 | /* Nexthops */ |
363be4dd RW |
182 | for (ALL_LIST_ELEMENTS_RO(route_info->nexthops, node, nexthop)) { |
183 | if (count >= MULTIPATH_NUM) | |
184 | break; | |
185 | api_nh = &api.nexthops[count]; | |
186 | if (fabricd) | |
187 | api_nh->onlink = true; | |
188 | api_nh->vrf_id = VRF_DEFAULT; | |
189 | ||
190 | switch (nexthop->family) { | |
191 | case AF_INET: | |
f80dd32b | 192 | /* FIXME: can it be ? */ |
363be4dd | 193 | if (nexthop->ip.ipv4.s_addr != INADDR_ANY) { |
f80dd32b | 194 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; |
363be4dd | 195 | api_nh->gate.ipv4 = nexthop->ip.ipv4; |
f80dd32b RW |
196 | } else { |
197 | api_nh->type = NEXTHOP_TYPE_IFINDEX; | |
198 | } | |
363be4dd RW |
199 | break; |
200 | case AF_INET6: | |
201 | if (!IN6_IS_ADDR_LINKLOCAL(&nexthop->ip.ipv6) | |
202 | && !IN6_IS_ADDR_UNSPECIFIED(&nexthop->ip.ipv6)) { | |
f80dd32b RW |
203 | continue; |
204 | } | |
363be4dd | 205 | api_nh->gate.ipv6 = nexthop->ip.ipv6; |
f80dd32b | 206 | api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; |
363be4dd RW |
207 | break; |
208 | default: | |
209 | flog_err(EC_LIB_DEVELOPMENT, | |
210 | "%s: unknown address family [%d]", __func__, | |
211 | nexthop->family); | |
212 | exit(1); | |
d62a17ae | 213 | } |
363be4dd RW |
214 | |
215 | api_nh->ifindex = nexthop->ifindex; | |
216 | count++; | |
d62a17ae | 217 | } |
c0721de4 RW |
218 | if (!count) |
219 | return; | |
f390d2c7 | 220 | |
c0721de4 | 221 | api.nexthop_num = count; |
f390d2c7 | 222 | |
c0721de4 | 223 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
eb5d44eb | 224 | } |
225 | ||
0a5f3f4f RW |
226 | void isis_zebra_route_del_route(struct prefix *prefix, |
227 | struct prefix_ipv6 *src_p, | |
228 | struct isis_route_info *route_info) | |
eb5d44eb | 229 | { |
c0721de4 | 230 | struct zapi_route api; |
d62a17ae | 231 | |
0a5f3f4f | 232 | if (zclient->sock < 0) |
d62a17ae | 233 | return; |
234 | ||
c0721de4 | 235 | memset(&api, 0, sizeof(api)); |
d62a17ae | 236 | api.vrf_id = VRF_DEFAULT; |
7c0cbd0e | 237 | api.type = PROTO_TYPE; |
d62a17ae | 238 | api.safi = SAFI_UNICAST; |
c0721de4 | 239 | api.prefix = *prefix; |
321c1bbb CF |
240 | if (src_p && src_p->prefixlen) { |
241 | api.src_prefix = *src_p; | |
242 | SET_FLAG(api.message, ZAPI_MESSAGE_SRCPFX); | |
243 | } | |
f390d2c7 | 244 | |
c0721de4 | 245 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); |
eb5d44eb | 246 | } |
247 | ||
121f9dee | 248 | static int isis_zebra_read(ZAPI_CALLBACK_ARGS) |
eb5d44eb | 249 | { |
74489921 | 250 | struct zapi_route api; |
d62a17ae | 251 | |
74489921 RW |
252 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
253 | return -1; | |
d62a17ae | 254 | |
9fb2b879 DS |
255 | if (api.prefix.family == AF_INET6 |
256 | && IN6_IS_ADDR_LINKLOCAL(&api.prefix.u.prefix6)) | |
257 | return 0; | |
258 | ||
d62a17ae | 259 | /* |
260 | * Avoid advertising a false default reachability. (A default | |
261 | * route installed by IS-IS gets redistributed from zebra back | |
262 | * into IS-IS causing us to start advertising default reachabity | |
263 | * without this check) | |
264 | */ | |
d43d2df5 CF |
265 | if (api.prefix.prefixlen == 0 |
266 | && api.src_prefix.prefixlen == 0 | |
7c0cbd0e | 267 | && api.type == PROTO_TYPE) { |
121f9dee | 268 | cmd = ZEBRA_REDISTRIBUTE_ROUTE_DEL; |
d43d2df5 | 269 | } |
d62a17ae | 270 | |
121f9dee | 271 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) |
d43d2df5 CF |
272 | isis_redist_add(api.type, &api.prefix, &api.src_prefix, |
273 | api.distance, api.metric); | |
d62a17ae | 274 | else |
d43d2df5 | 275 | isis_redist_delete(api.type, &api.prefix, &api.src_prefix); |
d62a17ae | 276 | |
277 | return 0; | |
eb5d44eb | 278 | } |
eb5d44eb | 279 | |
d62a17ae | 280 | int isis_distribute_list_update(int routetype) |
eb5d44eb | 281 | { |
d62a17ae | 282 | return 0; |
eb5d44eb | 283 | } |
284 | ||
d62a17ae | 285 | void isis_zebra_redistribute_set(afi_t afi, int type) |
eb5d44eb | 286 | { |
d62a17ae | 287 | if (type == DEFAULT_ROUTE) |
288 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, | |
49db7a7b | 289 | zclient, afi, VRF_DEFAULT); |
d62a17ae | 290 | else |
291 | zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type, | |
292 | 0, VRF_DEFAULT); | |
f3ccedaa CF |
293 | } |
294 | ||
d62a17ae | 295 | void isis_zebra_redistribute_unset(afi_t afi, int type) |
f3ccedaa | 296 | { |
d62a17ae | 297 | if (type == DEFAULT_ROUTE) |
298 | zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, | |
49db7a7b | 299 | zclient, afi, VRF_DEFAULT); |
d62a17ae | 300 | else |
301 | zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, | |
302 | type, 0, VRF_DEFAULT); | |
eb5d44eb | 303 | } |
304 | ||
d62a17ae | 305 | static void isis_zebra_connected(struct zclient *zclient) |
7076bb2f | 306 | { |
d62a17ae | 307 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
7076bb2f FL |
308 | } |
309 | ||
d62a17ae | 310 | void isis_zebra_init(struct thread_master *master) |
eb5d44eb | 311 | { |
26f63a1e | 312 | zclient = zclient_new(master, &zclient_options_default); |
7c0cbd0e | 313 | zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs); |
d62a17ae | 314 | zclient->zebra_connected = isis_zebra_connected; |
315 | zclient->router_id_update = isis_router_id_update_zebra; | |
d62a17ae | 316 | zclient->interface_address_add = isis_zebra_if_address_add; |
317 | zclient->interface_address_delete = isis_zebra_if_address_del; | |
318 | zclient->interface_link_params = isis_zebra_link_params; | |
74489921 RW |
319 | zclient->redistribute_route_add = isis_zebra_read; |
320 | zclient->redistribute_route_del = isis_zebra_read; | |
d62a17ae | 321 | |
322 | return; | |
eb5d44eb | 323 | } |
8d429559 | 324 | |
d62a17ae | 325 | void isis_zebra_stop(void) |
8d429559 | 326 | { |
d62a17ae | 327 | zclient_stop(zclient); |
328 | zclient_free(zclient); | |
8879bd22 | 329 | frr_fini(); |
8d429559 | 330 | } |