]>
Commit | Line | Data |
---|---|---|
7f57883e DS |
1 | /* |
2 | * Zebra connect library for EIGRP. | |
3 | * Copyright (C) 2013-2014 | |
4 | * Authors: | |
5 | * Donnie Savage | |
6 | * Jan Janovic | |
7 | * Matej Perina | |
8 | * Peter Orsag | |
9 | * Peter Paluch | |
10 | * | |
11 | * This file is part of GNU Zebra. | |
12 | * | |
13 | * GNU Zebra is free software; you can redistribute it and/or modify it | |
14 | * under the terms of the GNU General Public License as published by the | |
15 | * Free Software Foundation; either version 2, or (at your option) any | |
16 | * later version. | |
17 | * | |
18 | * GNU Zebra is distributed in the hope that it will be useful, but | |
19 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
21 | * General Public License for more details. | |
22 | * | |
896014f4 DL |
23 | * You should have received a copy of the GNU General Public License along |
24 | * with this program; see the file COPYING; if not, write to the Free Software | |
25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
7f57883e DS |
26 | */ |
27 | ||
28 | #include <zebra.h> | |
29 | ||
30 | #include "thread.h" | |
31 | #include "command.h" | |
32 | #include "network.h" | |
33 | #include "prefix.h" | |
34 | #include "routemap.h" | |
35 | #include "table.h" | |
36 | #include "stream.h" | |
37 | #include "memory.h" | |
38 | #include "zclient.h" | |
39 | #include "filter.h" | |
40 | #include "plist.h" | |
41 | #include "log.h" | |
42 | #include "nexthop.h" | |
43 | ||
44 | #include "eigrpd/eigrp_structs.h" | |
45 | #include "eigrpd/eigrpd.h" | |
46 | #include "eigrpd/eigrp_interface.h" | |
47 | #include "eigrpd/eigrp_neighbor.h" | |
48 | #include "eigrpd/eigrp_packet.h" | |
49 | #include "eigrpd/eigrp_zebra.h" | |
50 | #include "eigrpd/eigrp_vty.h" | |
51 | #include "eigrpd/eigrp_dump.h" | |
52 | #include "eigrpd/eigrp_network.h" | |
53 | #include "eigrpd/eigrp_topology.h" | |
54 | #include "eigrpd/eigrp_fsm.h" | |
55 | ||
121f9dee QY |
56 | static int eigrp_interface_address_add(ZAPI_CALLBACK_ARGS); |
57 | static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS); | |
d62a17ae | 58 | |
121f9dee | 59 | static int eigrp_zebra_read_route(ZAPI_CALLBACK_ARGS); |
7f57883e DS |
60 | |
61 | /* Zebra structure to hold current status. */ | |
62 | struct zclient *zclient = NULL; | |
63 | ||
64 | /* For registering threads. */ | |
65 | extern struct thread_master *master; | |
66 | struct in_addr router_id_zebra; | |
67 | ||
68 | /* Router-id update message from zebra. */ | |
121f9dee | 69 | static int eigrp_router_id_update_zebra(ZAPI_CALLBACK_ARGS) |
7f57883e | 70 | { |
d62a17ae | 71 | struct eigrp *eigrp; |
72 | struct prefix router_id; | |
73 | zebra_router_id_update_read(zclient->ibuf, &router_id); | |
7f57883e | 74 | |
d62a17ae | 75 | router_id_zebra = router_id.u.prefix4; |
7f57883e | 76 | |
e9449961 | 77 | eigrp = eigrp_lookup(vrf_id); |
7f57883e | 78 | |
d62a17ae | 79 | if (eigrp != NULL) |
80 | eigrp_router_id_update(eigrp); | |
7f57883e | 81 | |
d62a17ae | 82 | return 0; |
7f57883e DS |
83 | } |
84 | ||
121f9dee | 85 | static int eigrp_zebra_route_notify_owner(ZAPI_CALLBACK_ARGS) |
ca890872 DS |
86 | { |
87 | struct prefix p; | |
88 | enum zapi_route_notify_owner note; | |
28610f7e | 89 | uint32_t table; |
ca890872 | 90 | |
28610f7e | 91 | if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e)) |
ca890872 DS |
92 | return -1; |
93 | ||
94 | return 0; | |
95 | } | |
96 | ||
d62a17ae | 97 | static void eigrp_zebra_connected(struct zclient *zclient) |
08ff1a68 | 98 | { |
d62a17ae | 99 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
08ff1a68 | 100 | } |
7f57883e | 101 | |
d62a17ae | 102 | void eigrp_zebra_init(void) |
7f57883e | 103 | { |
996c9314 | 104 | struct zclient_options opt = {.receive_notify = false}; |
ca890872 | 105 | |
26f63a1e | 106 | zclient = zclient_new(master, &opt); |
d62a17ae | 107 | |
342213ea | 108 | zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs); |
d62a17ae | 109 | zclient->zebra_connected = eigrp_zebra_connected; |
110 | zclient->router_id_update = eigrp_router_id_update_zebra; | |
d62a17ae | 111 | zclient->interface_address_add = eigrp_interface_address_add; |
112 | zclient->interface_address_delete = eigrp_interface_address_delete; | |
74489921 RW |
113 | zclient->redistribute_route_add = eigrp_zebra_read_route; |
114 | zclient->redistribute_route_del = eigrp_zebra_read_route; | |
28b11f81 | 115 | zclient->route_notify_owner = eigrp_zebra_route_notify_owner; |
7f57883e DS |
116 | } |
117 | ||
118 | ||
119 | /* Zebra route add and delete treatment. */ | |
121f9dee | 120 | static int eigrp_zebra_read_route(ZAPI_CALLBACK_ARGS) |
7f57883e | 121 | { |
74489921 | 122 | struct zapi_route api; |
d62a17ae | 123 | struct eigrp *eigrp; |
124 | ||
74489921 RW |
125 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
126 | return -1; | |
d62a17ae | 127 | |
74489921 | 128 | if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr))) |
d62a17ae | 129 | return 0; |
130 | ||
e9449961 | 131 | eigrp = eigrp_lookup(vrf_id); |
d62a17ae | 132 | if (eigrp == NULL) |
133 | return 0; | |
134 | ||
121f9dee | 135 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { |
d62a17ae | 136 | |
121f9dee | 137 | } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ |
d62a17ae | 138 | { |
139 | } | |
140 | ||
141 | return 0; | |
7f57883e DS |
142 | } |
143 | ||
121f9dee | 144 | static int eigrp_interface_address_add(ZAPI_CALLBACK_ARGS) |
7f57883e | 145 | { |
d62a17ae | 146 | struct connected *c; |
7f57883e | 147 | |
121f9dee | 148 | c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
7f57883e | 149 | |
d62a17ae | 150 | if (c == NULL) |
151 | return 0; | |
7f57883e | 152 | |
d62a17ae | 153 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) { |
154 | char buf[128]; | |
155 | prefix2str(c->address, buf, sizeof(buf)); | |
156 | zlog_debug("Zebra: interface %s address add %s", c->ifp->name, | |
157 | buf); | |
158 | } | |
7f57883e | 159 | |
d62a17ae | 160 | eigrp_if_update(c->ifp); |
7f57883e | 161 | |
d62a17ae | 162 | return 0; |
7f57883e DS |
163 | } |
164 | ||
121f9dee | 165 | static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS) |
7f57883e | 166 | { |
d62a17ae | 167 | struct connected *c; |
168 | struct interface *ifp; | |
169 | struct eigrp_interface *ei; | |
7f57883e | 170 | |
121f9dee | 171 | c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
7f57883e | 172 | |
d62a17ae | 173 | if (c == NULL) |
174 | return 0; | |
7f57883e | 175 | |
d62a17ae | 176 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) { |
177 | char buf[128]; | |
178 | prefix2str(c->address, buf, sizeof(buf)); | |
179 | zlog_debug("Zebra: interface %s address delete %s", | |
180 | c->ifp->name, buf); | |
181 | } | |
7f57883e | 182 | |
d62a17ae | 183 | ifp = c->ifp; |
b748db67 DS |
184 | ei = ifp->info; |
185 | if (!ei) | |
d62a17ae | 186 | return 0; |
7f57883e | 187 | |
d62a17ae | 188 | /* Call interface hook functions to clean up */ |
84b5e534 DS |
189 | if (prefix_cmp(&ei->address, c->address) == 0) |
190 | eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA); | |
7f57883e | 191 | |
721c0857 | 192 | connected_free(&c); |
7f57883e | 193 | |
d62a17ae | 194 | return 0; |
7f57883e DS |
195 | } |
196 | ||
0e64ed02 DS |
197 | void eigrp_zebra_route_add(struct eigrp *eigrp, struct prefix *p, |
198 | struct list *successors, uint32_t distance) | |
7f57883e | 199 | { |
8fb753e3 RW |
200 | struct zapi_route api; |
201 | struct zapi_nexthop *api_nh; | |
255ab940 | 202 | struct eigrp_nexthop_entry *te; |
d62a17ae | 203 | struct listnode *node; |
8fb753e3 | 204 | int count = 0; |
d62a17ae | 205 | |
d00061ea RW |
206 | if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) |
207 | return; | |
208 | ||
8fb753e3 | 209 | memset(&api, 0, sizeof(api)); |
0e64ed02 | 210 | api.vrf_id = eigrp->vrf_id; |
8fb753e3 RW |
211 | api.type = ZEBRA_ROUTE_EIGRP; |
212 | api.safi = SAFI_UNICAST; | |
0f9bc496 | 213 | api.metric = distance; |
8fb753e3 | 214 | memcpy(&api.prefix, p, sizeof(*p)); |
d00061ea | 215 | |
8fb753e3 | 216 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); |
0f9bc496 | 217 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); |
d00061ea RW |
218 | |
219 | /* Nexthop, ifindex, distance and metric information. */ | |
220 | for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { | |
a74e593b RW |
221 | if (count >= MULTIPATH_NUM) |
222 | break; | |
8fb753e3 | 223 | api_nh = &api.nexthops[count]; |
0e64ed02 | 224 | api_nh->vrf_id = eigrp->vrf_id; |
d00061ea | 225 | if (te->adv_router->src.s_addr) { |
8fb753e3 RW |
226 | api_nh->gate.ipv4 = te->adv_router->src; |
227 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; | |
d00061ea | 228 | } else |
8fb753e3 RW |
229 | api_nh->type = NEXTHOP_TYPE_IFINDEX; |
230 | api_nh->ifindex = te->ei->ifp->ifindex; | |
231 | ||
232 | count++; | |
d00061ea | 233 | } |
a74e593b | 234 | api.nexthop_num = count; |
d62a17ae | 235 | |
d00061ea | 236 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { |
836aad7e DS |
237 | char buf[2][PREFIX_STRLEN]; |
238 | zlog_debug("Zebra: Route add %s nexthop %s", | |
239 | prefix2str(p, buf[0], PREFIX_STRLEN), | |
240 | inet_ntop(AF_INET, 0, buf[1], PREFIX_STRLEN)); | |
d00061ea | 241 | } |
d62a17ae | 242 | |
8fb753e3 | 243 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
7f57883e DS |
244 | } |
245 | ||
0e64ed02 | 246 | void eigrp_zebra_route_delete(struct eigrp *eigrp, struct prefix *p) |
7f57883e | 247 | { |
8fb753e3 | 248 | struct zapi_route api; |
d62a17ae | 249 | |
d00061ea RW |
250 | if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) |
251 | return; | |
252 | ||
8fb753e3 | 253 | memset(&api, 0, sizeof(api)); |
0e64ed02 | 254 | api.vrf_id = eigrp->vrf_id; |
d00061ea | 255 | api.type = ZEBRA_ROUTE_EIGRP; |
d00061ea | 256 | api.safi = SAFI_UNICAST; |
8fb753e3 RW |
257 | memcpy(&api.prefix, p, sizeof(*p)); |
258 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); | |
d00061ea RW |
259 | |
260 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { | |
836aad7e DS |
261 | char buf[PREFIX_STRLEN]; |
262 | zlog_debug("Zebra: Route del %s", | |
263 | prefix2str(p, buf, PREFIX_STRLEN)); | |
d62a17ae | 264 | } |
265 | ||
266 | return; | |
7f57883e DS |
267 | } |
268 | ||
0e64ed02 | 269 | static int eigrp_is_type_redistributed(int type, vrf_id_t vrf_id) |
7f57883e | 270 | { |
d62a17ae | 271 | return ((DEFAULT_ROUTE_TYPE(type)) |
49db7a7b | 272 | ? vrf_bitmap_check(zclient->default_information[AFI_IP], |
0e64ed02 | 273 | vrf_id) |
d62a17ae | 274 | : vrf_bitmap_check(zclient->redist[AFI_IP][type], |
0e64ed02 | 275 | vrf_id)); |
7f57883e DS |
276 | } |
277 | ||
d62a17ae | 278 | int eigrp_redistribute_set(struct eigrp *eigrp, int type, |
279 | struct eigrp_metrics metric) | |
7f57883e DS |
280 | { |
281 | ||
0e64ed02 | 282 | if (eigrp_is_type_redistributed(type, eigrp->vrf_id)) { |
d62a17ae | 283 | if (eigrp_metrics_is_same(metric, eigrp->dmetric[type])) { |
284 | eigrp->dmetric[type] = metric; | |
285 | } | |
7f57883e | 286 | |
d62a17ae | 287 | eigrp_external_routes_refresh(eigrp, type); |
7f57883e | 288 | |
d62a17ae | 289 | // if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) |
290 | // zlog_debug ("Redistribute[%s]: Refresh Type[%d], | |
291 | // Metric[%d]", | |
292 | // eigrp_redist_string(type), | |
293 | // metric_type (eigrp, type), metric_value | |
294 | // (eigrp, type)); | |
295 | return CMD_SUCCESS; | |
296 | } | |
7f57883e | 297 | |
d62a17ae | 298 | eigrp->dmetric[type] = metric; |
7f57883e | 299 | |
d62a17ae | 300 | zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0, |
daa64bdf | 301 | eigrp->vrf_id); |
7f57883e | 302 | |
d62a17ae | 303 | ++eigrp->redistribute; |
7f57883e | 304 | |
d62a17ae | 305 | return CMD_SUCCESS; |
7f57883e DS |
306 | } |
307 | ||
d62a17ae | 308 | int eigrp_redistribute_unset(struct eigrp *eigrp, int type) |
7f57883e DS |
309 | { |
310 | ||
0e64ed02 | 311 | if (eigrp_is_type_redistributed(type, eigrp->vrf_id)) { |
d62a17ae | 312 | memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics)); |
313 | zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, | |
daa64bdf | 314 | type, 0, eigrp->vrf_id); |
d62a17ae | 315 | --eigrp->redistribute; |
316 | } | |
7f57883e | 317 | |
d62a17ae | 318 | return CMD_SUCCESS; |
7f57883e | 319 | } |