]>
Commit | Line | Data |
---|---|---|
2fb975da TT |
1 | /* NHRP routing functions |
2 | * Copyright (c) 2014-2015 Timo Teräs | |
3 | * | |
4 | * This file is free software: you may copy, redistribute 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. | |
8 | */ | |
9 | ||
b45ac5f5 DL |
10 | #ifdef HAVE_CONFIG_H |
11 | #include "config.h" | |
12 | #endif | |
13 | ||
2fb975da TT |
14 | #include "nhrpd.h" |
15 | #include "table.h" | |
16 | #include "memory.h" | |
17 | #include "stream.h" | |
18 | #include "log.h" | |
19 | #include "zclient.h" | |
20 | ||
bf8d3d6a | 21 | DEFINE_MTYPE_STATIC(NHRPD, NHRP_ROUTE, "NHRP routing entry"); |
819dc8bb | 22 | |
2fb975da TT |
23 | static struct zclient *zclient; |
24 | static struct route_table *zebra_rib[AFI_MAX]; | |
25 | ||
26 | struct route_info { | |
27 | union sockunion via; | |
28 | struct interface *ifp; | |
29 | struct interface *nhrp_ifp; | |
30 | }; | |
31 | ||
996c9314 LB |
32 | static struct route_node *nhrp_route_update_get(const struct prefix *p, |
33 | int create) | |
2fb975da TT |
34 | { |
35 | struct route_node *rn; | |
36 | afi_t afi = family2afi(PREFIX_FAMILY(p)); | |
37 | ||
38 | if (!zebra_rib[afi]) | |
39 | return NULL; | |
40 | ||
41 | if (create) { | |
42 | rn = route_node_get(zebra_rib[afi], p); | |
43 | if (!rn->info) { | |
996c9314 LB |
44 | rn->info = XCALLOC(MTYPE_NHRP_ROUTE, |
45 | sizeof(struct route_info)); | |
2fb975da TT |
46 | route_lock_node(rn); |
47 | } | |
48 | return rn; | |
49 | } else { | |
50 | return route_node_lookup(zebra_rib[afi], p); | |
51 | } | |
52 | } | |
53 | ||
54 | static void nhrp_route_update_put(struct route_node *rn) | |
55 | { | |
56 | struct route_info *ri = rn->info; | |
57 | ||
996c9314 | 58 | if (!ri->ifp && !ri->nhrp_ifp |
ddd8d8c8 | 59 | && sockunion_is_null(&ri->via)) { |
2fb975da | 60 | XFREE(MTYPE_NHRP_ROUTE, rn->info); |
2fb975da TT |
61 | route_unlock_node(rn); |
62 | } | |
63 | route_unlock_node(rn); | |
64 | } | |
65 | ||
996c9314 LB |
66 | static void nhrp_route_update_zebra(const struct prefix *p, |
67 | union sockunion *nexthop, | |
68 | struct interface *ifp) | |
2fb975da TT |
69 | { |
70 | struct route_node *rn; | |
71 | struct route_info *ri; | |
72 | ||
ddd8d8c8 | 73 | rn = nhrp_route_update_get(p, !sockunion_is_null(nexthop) || ifp); |
2fb975da TT |
74 | if (rn) { |
75 | ri = rn->info; | |
76 | ri->via = *nexthop; | |
77 | ri->ifp = ifp; | |
78 | nhrp_route_update_put(rn); | |
79 | } | |
80 | } | |
81 | ||
b3b75104 PG |
82 | static void nhrp_zebra_register_neigh(vrf_id_t vrf_id, afi_t afi, bool reg) |
83 | { | |
84 | struct stream *s; | |
85 | ||
86 | if (!zclient || zclient->sock < 0) | |
87 | return; | |
88 | ||
89 | s = zclient->obuf; | |
90 | stream_reset(s); | |
91 | ||
92 | zclient_create_header(s, reg ? ZEBRA_NHRP_NEIGH_REGISTER : | |
93 | ZEBRA_NHRP_NEIGH_UNREGISTER, | |
94 | vrf_id); | |
95 | stream_putw(s, afi); | |
96 | stream_putw_at(s, 0, stream_get_endp(s)); | |
97 | zclient_send_message(zclient); | |
98 | } | |
99 | ||
2fb975da TT |
100 | void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp) |
101 | { | |
102 | struct route_node *rn; | |
103 | struct route_info *ri; | |
104 | ||
105 | rn = nhrp_route_update_get(p, ifp != NULL); | |
106 | if (rn) { | |
107 | ri = rn->info; | |
108 | ri->nhrp_ifp = ifp; | |
109 | nhrp_route_update_put(rn); | |
110 | } | |
111 | } | |
112 | ||
996c9314 LB |
113 | void nhrp_route_announce(int add, enum nhrp_cache_type type, |
114 | const struct prefix *p, struct interface *ifp, | |
115 | const union sockunion *nexthop, uint32_t mtu) | |
2fb975da | 116 | { |
9350687d RW |
117 | struct zapi_route api; |
118 | struct zapi_nexthop *api_nh; | |
a3e520f3 | 119 | union sockunion *nexthop_ref = (union sockunion *)nexthop; |
2fb975da TT |
120 | |
121 | if (zclient->sock < 0) | |
122 | return; | |
123 | ||
9350687d RW |
124 | memset(&api, 0, sizeof(api)); |
125 | api.type = ZEBRA_ROUTE_NHRP; | |
126 | api.safi = SAFI_UNICAST; | |
d5b2119c | 127 | api.vrf_id = VRF_DEFAULT; |
9350687d RW |
128 | api.prefix = *p; |
129 | ||
2fb975da TT |
130 | switch (type) { |
131 | case NHRP_CACHE_NEGATIVE: | |
09a484dd DL |
132 | zapi_route_set_blackhole(&api, BLACKHOLE_REJECT); |
133 | ifp = NULL; | |
134 | nexthop = NULL; | |
2fb975da TT |
135 | break; |
136 | case NHRP_CACHE_DYNAMIC: | |
137 | case NHRP_CACHE_NHS: | |
138 | case NHRP_CACHE_STATIC: | |
139 | /* Regular route, so these are announced | |
140 | * to other routing daemons */ | |
141 | break; | |
142 | default: | |
9350687d | 143 | SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE); |
2fb975da TT |
144 | break; |
145 | } | |
4e8b02f4 | 146 | SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); |
2fb975da | 147 | |
9350687d RW |
148 | SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); |
149 | api.nexthop_num = 1; | |
150 | api_nh = &api.nexthops[0]; | |
4a7371e9 | 151 | api_nh->vrf_id = VRF_DEFAULT; |
2fb975da | 152 | |
9350687d RW |
153 | switch (api.prefix.family) { |
154 | case AF_INET: | |
a3e520f3 PG |
155 | if (api.prefix.prefixlen == IPV4_MAX_BITLEN && |
156 | nexthop_ref && | |
157 | memcmp(&nexthop_ref->sin.sin_addr, &api.prefix.u.prefix4, | |
158 | sizeof(struct in_addr)) == 0) { | |
159 | nexthop_ref = NULL; | |
160 | } | |
161 | if (nexthop_ref) { | |
162 | api_nh->gate.ipv4 = nexthop_ref->sin.sin_addr; | |
6f27a9f6 | 163 | api_nh->type = NEXTHOP_TYPE_IPV4; |
2fb975da TT |
164 | } |
165 | if (ifp) { | |
6f27a9f6 RW |
166 | api_nh->ifindex = ifp->ifindex; |
167 | if (api_nh->type == NEXTHOP_TYPE_IPV4) | |
168 | api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; | |
169 | else | |
170 | api_nh->type = NEXTHOP_TYPE_IFINDEX; | |
2fb975da | 171 | } |
9350687d RW |
172 | break; |
173 | case AF_INET6: | |
a3e520f3 PG |
174 | if (api.prefix.prefixlen == IPV6_MAX_BITLEN && |
175 | nexthop_ref && | |
176 | memcmp(&nexthop_ref->sin6.sin6_addr, &api.prefix.u.prefix6, | |
177 | sizeof(struct in6_addr)) == 0) { | |
178 | nexthop_ref = NULL; | |
179 | } | |
180 | if (nexthop_ref) { | |
181 | api_nh->gate.ipv6 = nexthop_ref->sin6.sin6_addr; | |
6f27a9f6 | 182 | api_nh->type = NEXTHOP_TYPE_IPV6; |
37dc8ab5 TT |
183 | } |
184 | if (ifp) { | |
6f27a9f6 RW |
185 | api_nh->ifindex = ifp->ifindex; |
186 | if (api_nh->type == NEXTHOP_TYPE_IPV6) | |
187 | api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; | |
188 | else | |
189 | api_nh->type = NEXTHOP_TYPE_IFINDEX; | |
37dc8ab5 | 190 | } |
9350687d RW |
191 | break; |
192 | } | |
193 | if (mtu) { | |
194 | SET_FLAG(api.message, ZAPI_MESSAGE_MTU); | |
195 | api.mtu = mtu; | |
196 | } | |
37dc8ab5 | 197 | |
9350687d | 198 | if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) { |
2dbe669b | 199 | char buf[PREFIX_STRLEN]; |
37dc8ab5 | 200 | |
996c9314 | 201 | zlog_debug( |
2dbe669b DA |
202 | "Zebra send: route %s %pFX nexthop %s metric %u count %d dev %s", |
203 | add ? "add" : "del", &api.prefix, | |
a3e520f3 PG |
204 | nexthop_ref ? inet_ntop(api.prefix.family, |
205 | &api_nh->gate, | |
206 | buf, sizeof(buf)) | |
996c9314 | 207 | : "<onlink>", |
09a484dd | 208 | api.metric, api.nexthop_num, ifp ? ifp->name : "none"); |
2fb975da | 209 | } |
9350687d RW |
210 | |
211 | zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient, | |
212 | &api); | |
2fb975da TT |
213 | } |
214 | ||
121f9dee | 215 | int nhrp_route_read(ZAPI_CALLBACK_ARGS) |
2fb975da | 216 | { |
74489921 RW |
217 | struct zapi_route api; |
218 | struct zapi_nexthop *api_nh; | |
2fb975da | 219 | struct interface *ifp = NULL; |
2fb975da | 220 | union sockunion nexthop_addr; |
74489921 | 221 | int added; |
2fb975da | 222 | |
74489921 | 223 | if (zapi_route_decode(zclient->ibuf, &api) < 0) |
2fb975da | 224 | return -1; |
74489921 RW |
225 | |
226 | /* we completely ignore srcdest routes for now. */ | |
227 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) | |
c125d1d4 RW |
228 | return 0; |
229 | ||
b598a145 PG |
230 | /* ignore our routes */ |
231 | if (api.type == ZEBRA_ROUTE_NHRP) | |
232 | return 0; | |
233 | ||
74489921 RW |
234 | sockunion_family(&nexthop_addr) = AF_UNSPEC; |
235 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) { | |
236 | api_nh = &api.nexthops[0]; | |
237 | ||
238 | nexthop_addr.sa.sa_family = api.prefix.family; | |
239 | switch (nexthop_addr.sa.sa_family) { | |
240 | case AF_INET: | |
241 | nexthop_addr.sin.sin_addr = api_nh->gate.ipv4; | |
242 | break; | |
243 | case AF_INET6: | |
244 | nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6; | |
245 | break; | |
2fb975da | 246 | } |
74489921 RW |
247 | |
248 | if (api_nh->ifindex != IFINDEX_INTERNAL) | |
996c9314 | 249 | ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT); |
2fb975da | 250 | } |
2fb975da | 251 | |
74489921 | 252 | added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD); |
b6c48481 DS |
253 | debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %pFX via %pSU dev %s", |
254 | added ? "add" : "del", &api.prefix, &nexthop_addr, | |
996c9314 | 255 | ifp ? ifp->name : "(none)"); |
2fb975da | 256 | |
ddd8d8c8 | 257 | nhrp_route_update_zebra(&api.prefix, &nexthop_addr, added ? ifp : NULL); |
74489921 | 258 | nhrp_shortcut_prefix_change(&api.prefix, !added); |
2fb975da TT |
259 | |
260 | return 0; | |
261 | } | |
262 | ||
996c9314 LB |
263 | int nhrp_route_get_nexthop(const union sockunion *addr, struct prefix *p, |
264 | union sockunion *via, struct interface **ifp) | |
2fb975da TT |
265 | { |
266 | struct route_node *rn; | |
267 | struct route_info *ri; | |
268 | struct prefix lookup; | |
269 | afi_t afi = family2afi(sockunion_family(addr)); | |
2fb975da TT |
270 | |
271 | sockunion2hostprefix(addr, &lookup); | |
272 | ||
273 | rn = route_node_match(zebra_rib[afi], &lookup); | |
996c9314 LB |
274 | if (!rn) |
275 | return 0; | |
2fb975da TT |
276 | |
277 | ri = rn->info; | |
278 | if (ri->nhrp_ifp) { | |
2dbe669b | 279 | debugf(NHRP_DEBUG_ROUTE, "lookup %pFX: nhrp_if=%s", &lookup, |
996c9314 | 280 | ri->nhrp_ifp->name); |
2fb975da | 281 | |
996c9314 LB |
282 | if (via) |
283 | sockunion_family(via) = AF_UNSPEC; | |
284 | if (ifp) | |
285 | *ifp = ri->nhrp_ifp; | |
2fb975da | 286 | } else { |
2dbe669b DA |
287 | debugf(NHRP_DEBUG_ROUTE, "lookup %pFX: zebra route dev %s", |
288 | &lookup, ri->ifp ? ri->ifp->name : "(none)"); | |
2fb975da | 289 | |
996c9314 LB |
290 | if (via) |
291 | *via = ri->via; | |
292 | if (ifp) | |
293 | *ifp = ri->ifp; | |
2fb975da | 294 | } |
996c9314 LB |
295 | if (p) |
296 | *p = rn->p; | |
2fb975da TT |
297 | route_unlock_node(rn); |
298 | return 1; | |
299 | } | |
300 | ||
996c9314 LB |
301 | enum nhrp_route_type nhrp_route_address(struct interface *in_ifp, |
302 | union sockunion *addr, struct prefix *p, | |
303 | struct nhrp_peer **peer) | |
2fb975da TT |
304 | { |
305 | struct interface *ifp = in_ifp; | |
306 | struct nhrp_interface *nifp; | |
307 | struct nhrp_cache *c; | |
308 | union sockunion via[4]; | |
309 | uint32_t network_id = 0; | |
310 | afi_t afi = family2afi(sockunion_family(addr)); | |
311 | int i; | |
312 | ||
313 | if (ifp) { | |
314 | nifp = ifp->info; | |
315 | network_id = nifp->afi[afi].network_id; | |
316 | ||
317 | c = nhrp_cache_get(ifp, addr, 0); | |
318 | if (c && c->cur.type == NHRP_CACHE_LOCAL) { | |
996c9314 LB |
319 | if (p) |
320 | memset(p, 0, sizeof(*p)); | |
2fb975da TT |
321 | return NHRP_ROUTE_LOCAL; |
322 | } | |
323 | } | |
324 | ||
325 | for (i = 0; i < 4; i++) { | |
326 | if (!nhrp_route_get_nexthop(addr, p, &via[i], &ifp)) | |
327 | return NHRP_ROUTE_BLACKHOLE; | |
328 | if (ifp) { | |
329 | /* Departing from nbma network? */ | |
330 | nifp = ifp->info; | |
996c9314 LB |
331 | if (network_id |
332 | && network_id != nifp->afi[afi].network_id) | |
2fb975da TT |
333 | return NHRP_ROUTE_OFF_NBMA; |
334 | } | |
335 | if (sockunion_family(&via[i]) == AF_UNSPEC) | |
336 | break; | |
337 | /* Resolve via node, but return the prefix of first match */ | |
338 | addr = &via[i]; | |
339 | p = NULL; | |
340 | } | |
341 | ||
342 | if (ifp) { | |
343 | c = nhrp_cache_get(ifp, addr, 0); | |
344 | if (c && c->cur.type >= NHRP_CACHE_DYNAMIC) { | |
996c9314 LB |
345 | if (p) |
346 | memset(p, 0, sizeof(*p)); | |
2fb975da TT |
347 | if (c->cur.type == NHRP_CACHE_LOCAL) |
348 | return NHRP_ROUTE_LOCAL; | |
996c9314 LB |
349 | if (peer) |
350 | *peer = nhrp_peer_ref(c->cur.peer); | |
2fb975da TT |
351 | return NHRP_ROUTE_NBMA_NEXTHOP; |
352 | } | |
353 | } | |
354 | ||
355 | return NHRP_ROUTE_BLACKHOLE; | |
356 | } | |
357 | ||
996c9314 | 358 | static void nhrp_zebra_connected(struct zclient *zclient) |
a1f1bab0 JB |
359 | { |
360 | zclient_send_reg_requests(zclient, VRF_DEFAULT); | |
361 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, | |
996c9314 | 362 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); |
a1f1bab0 | 363 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, |
996c9314 | 364 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); |
b3b75104 PG |
365 | nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, true); |
366 | nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, true); | |
a1f1bab0 JB |
367 | } |
368 | ||
2fb975da TT |
369 | void nhrp_zebra_init(void) |
370 | { | |
371 | zebra_rib[AFI_IP] = route_table_init(); | |
372 | zebra_rib[AFI_IP6] = route_table_init(); | |
373 | ||
26f63a1e | 374 | zclient = zclient_new(master, &zclient_options_default); |
a1f1bab0 | 375 | zclient->zebra_connected = nhrp_zebra_connected; |
2fb975da TT |
376 | zclient->interface_address_add = nhrp_interface_address_add; |
377 | zclient->interface_address_delete = nhrp_interface_address_delete; | |
74489921 RW |
378 | zclient->redistribute_route_add = nhrp_route_read; |
379 | zclient->redistribute_route_del = nhrp_route_read; | |
b3b75104 PG |
380 | zclient->neighbor_added = nhrp_neighbor_operation; |
381 | zclient->neighbor_removed = nhrp_neighbor_operation; | |
382 | zclient->neighbor_get = nhrp_neighbor_operation; | |
7f48cfa5 | 383 | zclient->gre_update = nhrp_gre_update; |
342213ea | 384 | zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs); |
2fb975da TT |
385 | } |
386 | ||
7df171f5 DS |
387 | static void nhrp_table_node_cleanup(struct route_table *table, |
388 | struct route_node *node) | |
389 | { | |
390 | if (!node->info) | |
391 | return; | |
392 | ||
393 | XFREE(MTYPE_NHRP_ROUTE, node->info); | |
394 | } | |
395 | ||
f468a45a PG |
396 | void nhrp_send_zebra_configure_arp(struct interface *ifp, int family) |
397 | { | |
398 | struct stream *s; | |
399 | ||
400 | if (!zclient || zclient->sock < 0) { | |
401 | debugf(NHRP_DEBUG_COMMON, "%s() : zclient not ready", | |
402 | __func__); | |
403 | return; | |
404 | } | |
405 | s = zclient->obuf; | |
406 | stream_reset(s); | |
407 | zclient_create_header(s, | |
408 | ZEBRA_CONFIGURE_ARP, | |
409 | ifp->vrf_id); | |
410 | stream_putc(s, family); | |
411 | stream_putl(s, ifp->ifindex); | |
412 | stream_putw_at(s, 0, stream_get_endp(s)); | |
413 | zclient_send_message(zclient); | |
414 | } | |
415 | ||
7f48cfa5 PG |
416 | void nhrp_send_zebra_gre_source_set(struct interface *ifp, |
417 | unsigned int link_idx, | |
418 | vrf_id_t link_vrf_id) | |
419 | { | |
420 | struct stream *s; | |
421 | ||
422 | if (!zclient || zclient->sock < 0) { | |
423 | zlog_err("%s : zclient not ready", __func__); | |
424 | return; | |
425 | } | |
426 | if (link_idx == IFINDEX_INTERNAL || link_vrf_id == VRF_UNKNOWN) { | |
427 | /* silently ignore */ | |
428 | return; | |
429 | } | |
430 | s = zclient->obuf; | |
431 | stream_reset(s); | |
432 | zclient_create_header(s, | |
433 | ZEBRA_GRE_SOURCE_SET, | |
434 | ifp->vrf_id); | |
435 | stream_putl(s, ifp->ifindex); | |
436 | stream_putl(s, link_idx); | |
437 | stream_putl(s, link_vrf_id); | |
db51f0cd | 438 | stream_putl(s, 0); /* mtu provisioning */ |
7f48cfa5 PG |
439 | stream_putw_at(s, 0, stream_get_endp(s)); |
440 | zclient_send_message(zclient); | |
441 | } | |
442 | ||
05657ec2 PG |
443 | void nhrp_send_zebra_nbr(union sockunion *in, |
444 | union sockunion *out, | |
445 | struct interface *ifp) | |
446 | { | |
447 | struct stream *s; | |
448 | ||
449 | if (!zclient || zclient->sock < 0) | |
450 | return; | |
451 | s = zclient->obuf; | |
452 | stream_reset(s); | |
d603c077 PG |
453 | zclient_neigh_ip_encode(s, out ? ZEBRA_NEIGH_IP_ADD : |
454 | ZEBRA_NEIGH_IP_DEL, in, out, | |
455 | ifp); | |
05657ec2 PG |
456 | stream_putw_at(s, 0, stream_get_endp(s)); |
457 | zclient_send_message(zclient); | |
458 | } | |
459 | ||
7f48cfa5 PG |
460 | int nhrp_send_zebra_gre_request(struct interface *ifp) |
461 | { | |
462 | return zclient_send_zebra_gre_request(zclient, ifp); | |
463 | } | |
464 | ||
2fb975da TT |
465 | void nhrp_zebra_terminate(void) |
466 | { | |
b3b75104 PG |
467 | nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false); |
468 | nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, false); | |
2fb975da | 469 | zclient_stop(zclient); |
20a11b25 | 470 | zclient_free(zclient); |
7df171f5 DS |
471 | |
472 | zebra_rib[AFI_IP]->cleanup = nhrp_table_node_cleanup; | |
473 | zebra_rib[AFI_IP6]->cleanup = nhrp_table_node_cleanup; | |
2fb975da TT |
474 | route_table_finish(zebra_rib[AFI_IP]); |
475 | route_table_finish(zebra_rib[AFI_IP6]); | |
476 | } | |
7f48cfa5 PG |
477 | |
478 | void nhrp_gre_update(ZAPI_CALLBACK_ARGS) | |
479 | { | |
480 | struct stream *s; | |
481 | struct nhrp_gre_info gre_info, *val; | |
482 | struct interface *ifp; | |
483 | ||
484 | /* result */ | |
485 | s = zclient->ibuf; | |
486 | if (vrf_id != VRF_DEFAULT) | |
487 | return; | |
488 | ||
489 | /* read GRE information */ | |
490 | STREAM_GETL(s, gre_info.ifindex); | |
491 | STREAM_GETL(s, gre_info.ikey); | |
492 | STREAM_GETL(s, gre_info.okey); | |
493 | STREAM_GETL(s, gre_info.ifindex_link); | |
494 | STREAM_GETL(s, gre_info.vrfid_link); | |
495 | STREAM_GETL(s, gre_info.vtep_ip.s_addr); | |
496 | STREAM_GETL(s, gre_info.vtep_ip_remote.s_addr); | |
497 | if (gre_info.ifindex == IFINDEX_INTERNAL) | |
498 | val = NULL; | |
499 | else | |
500 | val = hash_lookup(nhrp_gre_list, &gre_info); | |
501 | if (val) { | |
502 | if (gre_info.vtep_ip.s_addr != val->vtep_ip.s_addr || | |
503 | gre_info.vrfid_link != val->vrfid_link || | |
504 | gre_info.ifindex_link != val->ifindex_link || | |
505 | gre_info.ikey != val->ikey || | |
506 | gre_info.okey != val->okey) { | |
507 | /* update */ | |
508 | memcpy(val, &gre_info, sizeof(struct nhrp_gre_info)); | |
509 | } | |
510 | } else { | |
511 | val = nhrp_gre_info_alloc(&gre_info); | |
512 | } | |
513 | ifp = if_lookup_by_index(gre_info.ifindex, vrf_id); | |
514 | debugf(NHRP_DEBUG_EVENT, "%s: gre interface %d vr %d obtained from system", | |
515 | ifp ? ifp->name : "<none>", gre_info.ifindex, vrf_id); | |
516 | if (ifp) | |
517 | nhrp_interface_update_nbma(ifp, val); | |
518 | return; | |
519 | stream_failure: | |
520 | zlog_err("%s(): error reading response ..", __func__); | |
521 | } |