]>
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 | ||
e9f1847e | 44 | #include "eigrpd/eigrp_types.h" |
7f57883e DS |
45 | #include "eigrpd/eigrp_structs.h" |
46 | #include "eigrpd/eigrpd.h" | |
47 | #include "eigrpd/eigrp_interface.h" | |
48 | #include "eigrpd/eigrp_neighbor.h" | |
49 | #include "eigrpd/eigrp_packet.h" | |
50 | #include "eigrpd/eigrp_zebra.h" | |
51 | #include "eigrpd/eigrp_vty.h" | |
52 | #include "eigrpd/eigrp_dump.h" | |
53 | #include "eigrpd/eigrp_network.h" | |
54 | #include "eigrpd/eigrp_topology.h" | |
55 | #include "eigrpd/eigrp_fsm.h" | |
e9f1847e | 56 | #include "eigrpd/eigrp_metric.h" |
7f57883e | 57 | |
121f9dee QY |
58 | static int eigrp_interface_address_add(ZAPI_CALLBACK_ARGS); |
59 | static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS); | |
d62a17ae | 60 | |
121f9dee | 61 | static int eigrp_zebra_read_route(ZAPI_CALLBACK_ARGS); |
7f57883e DS |
62 | |
63 | /* Zebra structure to hold current status. */ | |
64 | struct zclient *zclient = NULL; | |
65 | ||
66 | /* For registering threads. */ | |
67 | extern struct thread_master *master; | |
68 | struct in_addr router_id_zebra; | |
69 | ||
70 | /* Router-id update message from zebra. */ | |
121f9dee | 71 | static int eigrp_router_id_update_zebra(ZAPI_CALLBACK_ARGS) |
7f57883e | 72 | { |
d62a17ae | 73 | struct eigrp *eigrp; |
74 | struct prefix router_id; | |
75 | zebra_router_id_update_read(zclient->ibuf, &router_id); | |
7f57883e | 76 | |
d62a17ae | 77 | router_id_zebra = router_id.u.prefix4; |
7f57883e | 78 | |
e9449961 | 79 | eigrp = eigrp_lookup(vrf_id); |
7f57883e | 80 | |
d62a17ae | 81 | if (eigrp != NULL) |
82 | eigrp_router_id_update(eigrp); | |
7f57883e | 83 | |
d62a17ae | 84 | return 0; |
7f57883e DS |
85 | } |
86 | ||
121f9dee | 87 | static int eigrp_zebra_route_notify_owner(ZAPI_CALLBACK_ARGS) |
ca890872 DS |
88 | { |
89 | struct prefix p; | |
90 | enum zapi_route_notify_owner note; | |
28610f7e | 91 | uint32_t table; |
ca890872 | 92 | |
77b38a4a S |
93 | if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e, NULL, |
94 | NULL)) | |
ca890872 DS |
95 | return -1; |
96 | ||
97 | return 0; | |
98 | } | |
99 | ||
d62a17ae | 100 | static void eigrp_zebra_connected(struct zclient *zclient) |
08ff1a68 | 101 | { |
d62a17ae | 102 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
08ff1a68 | 103 | } |
7f57883e | 104 | |
a243d1db DL |
105 | static zclient_handler *const eigrp_handlers[] = { |
106 | [ZEBRA_ROUTER_ID_UPDATE] = eigrp_router_id_update_zebra, | |
107 | [ZEBRA_INTERFACE_ADDRESS_ADD] = eigrp_interface_address_add, | |
108 | [ZEBRA_INTERFACE_ADDRESS_DELETE] = eigrp_interface_address_delete, | |
109 | [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = eigrp_zebra_read_route, | |
110 | [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = eigrp_zebra_read_route, | |
111 | [ZEBRA_ROUTE_NOTIFY_OWNER] = eigrp_zebra_route_notify_owner, | |
112 | }; | |
113 | ||
d62a17ae | 114 | void eigrp_zebra_init(void) |
7f57883e | 115 | { |
996c9314 | 116 | struct zclient_options opt = {.receive_notify = false}; |
ca890872 | 117 | |
a243d1db DL |
118 | zclient = zclient_new(master, &opt, eigrp_handlers, |
119 | array_size(eigrp_handlers)); | |
d62a17ae | 120 | |
342213ea | 121 | zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs); |
d62a17ae | 122 | zclient->zebra_connected = eigrp_zebra_connected; |
7f57883e DS |
123 | } |
124 | ||
125 | ||
126 | /* Zebra route add and delete treatment. */ | |
121f9dee | 127 | static int eigrp_zebra_read_route(ZAPI_CALLBACK_ARGS) |
7f57883e | 128 | { |
74489921 | 129 | struct zapi_route api; |
d62a17ae | 130 | struct eigrp *eigrp; |
131 | ||
74489921 RW |
132 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
133 | return -1; | |
d62a17ae | 134 | |
74489921 | 135 | if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr))) |
d62a17ae | 136 | return 0; |
137 | ||
e9449961 | 138 | eigrp = eigrp_lookup(vrf_id); |
d62a17ae | 139 | if (eigrp == NULL) |
140 | return 0; | |
141 | ||
121f9dee | 142 | if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { |
d62a17ae | 143 | |
121f9dee | 144 | } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ |
d62a17ae | 145 | { |
146 | } | |
147 | ||
148 | return 0; | |
7f57883e DS |
149 | } |
150 | ||
121f9dee | 151 | static int eigrp_interface_address_add(ZAPI_CALLBACK_ARGS) |
7f57883e | 152 | { |
d62a17ae | 153 | struct connected *c; |
7f57883e | 154 | |
121f9dee | 155 | c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
7f57883e | 156 | |
d62a17ae | 157 | if (c == NULL) |
158 | return 0; | |
7f57883e | 159 | |
2dbe669b DA |
160 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) |
161 | zlog_debug("Zebra: interface %s address add %pFX", c->ifp->name, | |
162 | c->address); | |
7f57883e | 163 | |
d62a17ae | 164 | eigrp_if_update(c->ifp); |
7f57883e | 165 | |
d62a17ae | 166 | return 0; |
7f57883e DS |
167 | } |
168 | ||
121f9dee | 169 | static int eigrp_interface_address_delete(ZAPI_CALLBACK_ARGS) |
7f57883e | 170 | { |
d62a17ae | 171 | struct connected *c; |
172 | struct interface *ifp; | |
173 | struct eigrp_interface *ei; | |
7f57883e | 174 | |
121f9dee | 175 | c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id); |
7f57883e | 176 | |
d62a17ae | 177 | if (c == NULL) |
178 | return 0; | |
7f57883e | 179 | |
2dbe669b DA |
180 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) |
181 | zlog_debug("Zebra: interface %s address delete %pFX", | |
182 | c->ifp->name, c->address); | |
7f57883e | 183 | |
d62a17ae | 184 | ifp = c->ifp; |
b748db67 DS |
185 | ei = ifp->info; |
186 | if (!ei) | |
d62a17ae | 187 | return 0; |
7f57883e | 188 | |
d62a17ae | 189 | /* Call interface hook functions to clean up */ |
84b5e534 DS |
190 | if (prefix_cmp(&ei->address, c->address) == 0) |
191 | eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA); | |
7f57883e | 192 | |
721c0857 | 193 | connected_free(&c); |
7f57883e | 194 | |
d62a17ae | 195 | return 0; |
7f57883e DS |
196 | } |
197 | ||
0e64ed02 DS |
198 | void eigrp_zebra_route_add(struct eigrp *eigrp, struct prefix *p, |
199 | struct list *successors, uint32_t distance) | |
7f57883e | 200 | { |
8fb753e3 RW |
201 | struct zapi_route api; |
202 | struct zapi_nexthop *api_nh; | |
dc4accdd | 203 | struct eigrp_route_descriptor *te; |
d62a17ae | 204 | struct listnode *node; |
8fb753e3 | 205 | int count = 0; |
d62a17ae | 206 | |
d00061ea RW |
207 | if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) |
208 | return; | |
209 | ||
8fb753e3 | 210 | memset(&api, 0, sizeof(api)); |
0e64ed02 | 211 | api.vrf_id = eigrp->vrf_id; |
8fb753e3 RW |
212 | api.type = ZEBRA_ROUTE_EIGRP; |
213 | api.safi = SAFI_UNICAST; | |
0f9bc496 | 214 | api.metric = distance; |
8fb753e3 | 215 | memcpy(&api.prefix, p, sizeof(*p)); |
d00061ea | 216 | |
8fb753e3 | 217 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); |
0f9bc496 | 218 | SET_FLAG(api.message, ZAPI_MESSAGE_METRIC); |
d00061ea RW |
219 | |
220 | /* Nexthop, ifindex, distance and metric information. */ | |
221 | for (ALL_LIST_ELEMENTS_RO(successors, node, te)) { | |
a74e593b RW |
222 | if (count >= MULTIPATH_NUM) |
223 | break; | |
8fb753e3 | 224 | api_nh = &api.nexthops[count]; |
0e64ed02 | 225 | api_nh->vrf_id = eigrp->vrf_id; |
d00061ea | 226 | if (te->adv_router->src.s_addr) { |
8fb753e3 RW |
227 | api_nh->gate.ipv4 = te->adv_router->src; |
228 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; | |
d00061ea | 229 | } else |
8fb753e3 RW |
230 | api_nh->type = NEXTHOP_TYPE_IFINDEX; |
231 | api_nh->ifindex = te->ei->ifp->ifindex; | |
232 | ||
233 | count++; | |
d00061ea | 234 | } |
a74e593b | 235 | api.nexthop_num = count; |
d62a17ae | 236 | |
d00061ea | 237 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) { |
4f278784 | 238 | zlog_debug("Zebra: Route add %pFX", p); |
d00061ea | 239 | } |
d62a17ae | 240 | |
8fb753e3 | 241 | zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api); |
7f57883e DS |
242 | } |
243 | ||
0e64ed02 | 244 | void eigrp_zebra_route_delete(struct eigrp *eigrp, struct prefix *p) |
7f57883e | 245 | { |
8fb753e3 | 246 | struct zapi_route api; |
d62a17ae | 247 | |
d00061ea RW |
248 | if (!zclient->redist[AFI_IP][ZEBRA_ROUTE_EIGRP]) |
249 | return; | |
250 | ||
8fb753e3 | 251 | memset(&api, 0, sizeof(api)); |
0e64ed02 | 252 | api.vrf_id = eigrp->vrf_id; |
d00061ea | 253 | api.type = ZEBRA_ROUTE_EIGRP; |
d00061ea | 254 | api.safi = SAFI_UNICAST; |
8fb753e3 RW |
255 | memcpy(&api.prefix, p, sizeof(*p)); |
256 | zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api); | |
d00061ea | 257 | |
2dbe669b DA |
258 | if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) |
259 | zlog_debug("Zebra: Route del %pFX", p); | |
d62a17ae | 260 | |
261 | return; | |
7f57883e DS |
262 | } |
263 | ||
0e64ed02 | 264 | static int eigrp_is_type_redistributed(int type, vrf_id_t vrf_id) |
7f57883e | 265 | { |
d62a17ae | 266 | return ((DEFAULT_ROUTE_TYPE(type)) |
49db7a7b | 267 | ? vrf_bitmap_check(zclient->default_information[AFI_IP], |
0e64ed02 | 268 | vrf_id) |
d62a17ae | 269 | : vrf_bitmap_check(zclient->redist[AFI_IP][type], |
0e64ed02 | 270 | vrf_id)); |
7f57883e DS |
271 | } |
272 | ||
d62a17ae | 273 | int eigrp_redistribute_set(struct eigrp *eigrp, int type, |
274 | struct eigrp_metrics metric) | |
7f57883e DS |
275 | { |
276 | ||
0e64ed02 | 277 | if (eigrp_is_type_redistributed(type, eigrp->vrf_id)) { |
d62a17ae | 278 | if (eigrp_metrics_is_same(metric, eigrp->dmetric[type])) { |
279 | eigrp->dmetric[type] = metric; | |
280 | } | |
7f57883e | 281 | |
d62a17ae | 282 | eigrp_external_routes_refresh(eigrp, type); |
7f57883e | 283 | |
d62a17ae | 284 | // if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) |
285 | // zlog_debug ("Redistribute[%s]: Refresh Type[%d], | |
286 | // Metric[%d]", | |
287 | // eigrp_redist_string(type), | |
288 | // metric_type (eigrp, type), metric_value | |
289 | // (eigrp, type)); | |
290 | return CMD_SUCCESS; | |
291 | } | |
7f57883e | 292 | |
d62a17ae | 293 | eigrp->dmetric[type] = metric; |
7f57883e | 294 | |
d62a17ae | 295 | zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type, 0, |
daa64bdf | 296 | eigrp->vrf_id); |
7f57883e | 297 | |
d62a17ae | 298 | ++eigrp->redistribute; |
7f57883e | 299 | |
d62a17ae | 300 | return CMD_SUCCESS; |
7f57883e DS |
301 | } |
302 | ||
d62a17ae | 303 | int eigrp_redistribute_unset(struct eigrp *eigrp, int type) |
7f57883e DS |
304 | { |
305 | ||
0e64ed02 | 306 | if (eigrp_is_type_redistributed(type, eigrp->vrf_id)) { |
d62a17ae | 307 | memset(&eigrp->dmetric[type], 0, sizeof(struct eigrp_metrics)); |
308 | zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, | |
daa64bdf | 309 | type, 0, eigrp->vrf_id); |
d62a17ae | 310 | --eigrp->redistribute; |
311 | } | |
7f57883e | 312 | |
d62a17ae | 313 | return CMD_SUCCESS; |
7f57883e | 314 | } |