]> git.proxmox.com Git - mirror_frr.git/blame - zebra/connected.c
Merge pull request #1059 from opensourcerouting/oldbits-1
[mirror_frr.git] / zebra / connected.c
CommitLineData
718e3744 1/*
2 * Address linked list routine.
3 * Copyright (C) 1997, 98 Kunihiro Ishiguro
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 20 */
21
22#include <zebra.h>
23
24#include "prefix.h"
25#include "linklist.h"
26#include "if.h"
27#include "table.h"
28#include "rib.h"
29#include "table.h"
30#include "log.h"
0752ef0b 31#include "memory.h"
4a1ab8e4 32#include "zebra_memory.h"
718e3744 33
82f97584 34#include "vty.h"
b84c7253 35#include "zebra/debug.h"
718e3744 36#include "zebra/zserv.h"
37#include "zebra/redistribute.h"
eef1fe11 38#include "zebra/interface.h"
a1ac18c4 39#include "zebra/connected.h"
b6120505 40#include "zebra/rtadv.h"
40c7bdb0 41#include "zebra/zebra_mpls.h"
939fba27 42#include "zebra/debug.h"
6b0655a2 43
02b4805f 44/* communicate the withdrawal of a connected address */
d62a17ae 45static void connected_withdraw(struct connected *ifc)
ca16218d 46{
d62a17ae 47 if (!ifc)
48 return;
ca16218d 49
d62a17ae 50 /* Update interface address information to protocol daemon. */
51 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) {
52 zebra_interface_address_delete_update(ifc->ifp, ifc);
ca16218d 53
d62a17ae 54 if (ifc->address->family == AF_INET)
55 if_subnet_delete(ifc->ifp, ifc);
9db047fc 56
d62a17ae 57 if (ifc->address->family == AF_INET)
58 connected_down_ipv4(ifc->ifp, ifc);
59 else
60 connected_down_ipv6(ifc->ifp, ifc);
ca16218d 61
d62a17ae 62 UNSET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
63 }
ca16218d 64
d62a17ae 65 /* The address is not in the kernel anymore, so clear the flag */
66 UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
f7f740fe 67
d62a17ae 68 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) {
69 listnode_delete(ifc->ifp->connected, ifc);
70 connected_free(ifc);
71 }
ca16218d 72}
73
d62a17ae 74static void connected_announce(struct interface *ifp, struct connected *ifc)
ca16218d 75{
d62a17ae 76 if (!ifc)
77 return;
78
79 if (!if_is_loopback(ifp) && ifc->address->family == AF_INET) {
80 if (ifc->address->prefixlen == 32)
81 SET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
82 else
83 UNSET_FLAG(ifc->flags, ZEBRA_IFA_UNNUMBERED);
84 }
85
86 listnode_add(ifp->connected, ifc);
87
88 /* Update interface address information to protocol daemon. */
89 if (ifc->address->family == AF_INET)
90 if_subnet_add(ifp, ifc);
91
92 zebra_interface_address_add_update(ifp, ifc);
93
94 if (if_is_operative(ifp)) {
95 if (ifc->address->family == AF_INET)
96 connected_up_ipv4(ifp, ifc);
97 else
98 connected_up_ipv6(ifp, ifc);
99 }
ca16218d 100}
6b0655a2 101
718e3744 102/* If same interface address is already exist... */
abffde07
DL
103struct connected *connected_check(struct interface *ifp,
104 union prefixconstptr pu)
718e3744 105{
abffde07 106 const struct prefix *p = pu.p;
d62a17ae 107 struct connected *ifc;
108 struct listnode *node;
718e3744 109
d62a17ae 110 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
111 if (prefix_same(ifc->address, p))
112 return ifc;
718e3744 113
d62a17ae 114 return NULL;
718e3744 115}
116
abffde07
DL
117/* same, but with peer address */
118struct connected *connected_check_ptp(struct interface *ifp,
119 union prefixconstptr pu,
120 union prefixconstptr du)
121{
122 const struct prefix *p = pu.p;
123 const struct prefix *d = du.p;
124 struct connected *ifc;
125 struct listnode *node;
126
127 /* ignore broadcast addresses */
128 if (p->prefixlen != IPV4_MAX_PREFIXLEN)
129 d = NULL;
130
131 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
132 if (!prefix_same(ifc->address, p))
133 continue;
134 if (!CONNECTED_PEER(ifc) && !d)
135 return ifc;
136 if (CONNECTED_PEER(ifc) && d
137 && prefix_same(ifc->destination, d))
138 return ifc;
139 }
140
141 return NULL;
142}
143
02b4805f 144/* Check if two ifc's describe the same address in the same state */
d62a17ae 145static int connected_same(struct connected *ifc1, struct connected *ifc2)
74ecdc9e 146{
d62a17ae 147 if (ifc1->ifp != ifc2->ifp)
148 return 0;
149
150 if (ifc1->destination)
151 if (!ifc2->destination)
152 return 0;
153 if (ifc2->destination)
154 if (!ifc1->destination)
155 return 0;
156
157 if (ifc1->destination && ifc2->destination)
158 if (!prefix_same(ifc1->destination, ifc2->destination))
159 return 0;
160
161 if (ifc1->flags != ifc2->flags)
162 return 0;
163
164 if (ifc1->conf != ifc2->conf)
165 return 0;
166
167 return 1;
74ecdc9e
PJ
168}
169
d7f5dad6
CF
170/* Handle changes to addresses and send the neccesary announcements
171 * to clients. */
d62a17ae 172static void connected_update(struct interface *ifp, struct connected *ifc)
74ecdc9e 173{
d62a17ae 174 struct connected *current;
175
176 /* Check same connected route. */
abffde07
DL
177 current = connected_check_ptp(ifp, ifc->address, ifc->destination);
178 if (current) {
d62a17ae 179 if (CHECK_FLAG(current->conf, ZEBRA_IFC_CONFIGURED))
180 SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
181
182 /* Avoid spurious withdraws, this might be just the kernel
183 * 'reflecting'
184 * back an address we have already added.
185 */
186 if (connected_same(current, ifc)) {
187 /* nothing to do */
188 connected_free(ifc);
189 return;
190 }
191
192 /* Clear the configured flag on the old ifc, so it will be freed
193 * by
194 * connected withdraw. */
195 UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
196 connected_withdraw(
197 current); /* implicit withdraw - freebsd does this */
198 }
199
200 /* If the connected is new or has changed, announce it, if it is usable
201 */
202 if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
203 connected_announce(ifp, ifc);
74ecdc9e
PJ
204}
205
718e3744 206/* Called from if_up(). */
d62a17ae 207void connected_up_ipv4(struct interface *ifp, struct connected *ifc)
718e3744 208{
d62a17ae 209 struct prefix p;
fd36be7e
DL
210 struct nexthop nh = {
211 .type = NEXTHOP_TYPE_IFINDEX,
212 .ifindex = ifp->ifindex,
213 };
d62a17ae 214
215 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
216 return;
217
218 PREFIX_COPY_IPV4((struct prefix_ipv4 *)&p, CONNECTED_PREFIX(ifc));
219
220 /* Apply mask to the network. */
221 apply_mask(&p);
222
223 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
224 address. */
225 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
226 return;
227
228 rib_add(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
fd36be7e 229 &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
d62a17ae 230
231 rib_add(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
fd36be7e 232 &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
d62a17ae 233
234 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
235 zlog_debug(
236 "%u: IF %s IPv4 address add/up, scheduling RIB processing",
237 ifp->vrf_id, ifp->name);
238 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
239
240 /* Schedule LSP forwarding entries for processing, if appropriate. */
241 if (ifp->vrf_id == VRF_DEFAULT) {
242 if (IS_ZEBRA_DEBUG_MPLS)
243 zlog_debug(
244 "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
245 ifp->vrf_id, ifp->name);
246 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
247 }
718e3744 248}
249
250/* Add connected IPv4 route to the interface. */
d62a17ae 251void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
252 u_char prefixlen, struct in_addr *broad,
253 const char *label)
718e3744 254{
d62a17ae 255 struct prefix_ipv4 *p;
256 struct connected *ifc;
257
258 if (ipv4_martian(addr))
259 return;
260
261 /* Make connected structure. */
262 ifc = connected_new();
263 ifc->ifp = ifp;
264 ifc->flags = flags;
265 /* If we get a notification from the kernel,
266 * we can safely assume the address is known to the kernel */
267 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
268
269 /* Allocate new connected address. */
270 p = prefix_ipv4_new();
271 p->family = AF_INET;
272 p->prefix = *addr;
abffde07
DL
273 p->prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
274 : prefixlen;
d62a17ae 275 ifc->address = (struct prefix *)p;
276
277 /* If there is broadcast or peer address. */
278 if (broad) {
279 p = prefix_ipv4_new();
280 p->family = AF_INET;
281 p->prefix = *broad;
282 p->prefixlen = prefixlen;
283 ifc->destination = (struct prefix *)p;
284
285 /* validate the destination address */
286 if (CONNECTED_PEER(ifc)) {
287 if (IPV4_ADDR_SAME(addr, broad))
288 zlog_warn(
289 "warning: interface %s has same local and peer "
290 "address %s, routing protocols may malfunction",
291 ifp->name, inet_ntoa(*addr));
292 } else {
293 if (broad->s_addr
294 != ipv4_broadcast_addr(addr->s_addr, prefixlen)) {
295 char buf[2][INET_ADDRSTRLEN];
296 struct in_addr bcalc;
297 bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,
298 prefixlen);
299 zlog_warn(
300 "warning: interface %s broadcast addr %s/%d != "
301 "calculated %s, routing protocols may malfunction",
302 ifp->name,
303 inet_ntop(AF_INET, broad, buf[0],
304 sizeof(buf[0])),
305 prefixlen,
306 inet_ntop(AF_INET, &bcalc, buf[1],
307 sizeof(buf[1])));
308 }
309 }
310
311 } else {
312 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
313 zlog_warn(
314 "warning: %s called for interface %s "
315 "with peer flag set, but no peer address supplied",
316 __func__, ifp->name);
317 UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
318 }
319
320 /* no broadcast or destination address was supplied */
321 if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
322 zlog_warn(
323 "warning: PtP interface %s with addr %s/%d needs a "
324 "peer address",
325 ifp->name, inet_ntoa(*addr), prefixlen);
e4529636
AS
326 }
327
d62a17ae 328 /* Label of this address. */
329 if (label)
330 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
718e3744 331
d62a17ae 332 /* For all that I know an IPv4 address is always ready when we receive
333 * the notification. So it should be safe to set the REAL flag here. */
334 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
718e3744 335
d62a17ae 336 connected_update(ifp, ifc);
718e3744 337}
338
d62a17ae 339void connected_down_ipv4(struct interface *ifp, struct connected *ifc)
718e3744 340{
d62a17ae 341 struct prefix p;
fd36be7e
DL
342 struct nexthop nh = {
343 .type = NEXTHOP_TYPE_IFINDEX,
344 .ifindex = ifp->ifindex,
345 };
718e3744 346
d62a17ae 347 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
348 return;
718e3744 349
d62a17ae 350 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
718e3744 351
d62a17ae 352 /* Apply mask to the network. */
353 apply_mask(&p);
718e3744 354
d62a17ae 355 /* In case of connected address is 0.0.0.0/0 we treat it tunnel
356 address. */
357 if (prefix_ipv4_any((struct prefix_ipv4 *)&p))
358 return;
718e3744 359
d62a17ae 360 /* Same logic as for connected_up_ipv4(): push the changes into the
361 * head. */
362 rib_delete(AFI_IP, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
fd36be7e 363 &p, NULL, &nh, 0, 0);
718e3744 364
d62a17ae 365 rib_delete(AFI_IP, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
fd36be7e 366 0, &p, NULL, &nh, 0, 0);
42cb6b66 367
d62a17ae 368 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
369 zlog_debug(
370 "%u: IF %s IPv4 address down, scheduling RIB processing",
371 ifp->vrf_id, ifp->name);
b84c7253 372
d62a17ae 373 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
40c7bdb0 374
d62a17ae 375 /* Schedule LSP forwarding entries for processing, if appropriate. */
376 if (ifp->vrf_id == VRF_DEFAULT) {
377 if (IS_ZEBRA_DEBUG_MPLS)
378 zlog_debug(
379 "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
380 ifp->vrf_id, ifp->name);
381 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
382 }
718e3744 383}
384
385/* Delete connected IPv4 route to the interface. */
d62a17ae 386void connected_delete_ipv4(struct interface *ifp, int flags,
387 struct in_addr *addr, u_char prefixlen,
388 struct in_addr *broad)
718e3744 389{
abffde07 390 struct prefix_ipv4 p, d;
d62a17ae 391 struct connected *ifc;
392
393 memset(&p, 0, sizeof(struct prefix_ipv4));
394 p.family = AF_INET;
395 p.prefix = *addr;
abffde07
DL
396 p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
397 : prefixlen;
398
399 if (broad) {
400 memset(&d, 0, sizeof(struct prefix_ipv4));
401 d.family = AF_INET;
402 d.prefix = *broad;
403 d.prefixlen = prefixlen;
404 ifc = connected_check_ptp(ifp, (struct prefix *)&p,
405 (struct prefix *)&d);
406 } else
407 ifc = connected_check_ptp(ifp, (struct prefix *)&p, NULL);
d62a17ae 408
d62a17ae 409 if (!ifc)
410 return;
411
412 connected_withdraw(ifc);
413
414 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
415 zlog_debug(
416 "%u: IF %s IPv4 address del, scheduling RIB processing",
417 ifp->vrf_id, ifp->name);
418
419 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
420
421 /* Schedule LSP forwarding entries for processing, if appropriate. */
422 if (ifp->vrf_id == VRF_DEFAULT) {
423 if (IS_ZEBRA_DEBUG_MPLS)
424 zlog_debug(
425 "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
426 ifp->vrf_id, ifp->name);
427 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
428 }
718e3744 429}
430
d62a17ae 431void connected_up_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 432{
d62a17ae 433 struct prefix p;
fd36be7e
DL
434 struct nexthop nh = {
435 .type = NEXTHOP_TYPE_IFINDEX,
436 .ifindex = ifp->ifindex,
437 };
718e3744 438
d62a17ae 439 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
440 return;
718e3744 441
d62a17ae 442 PREFIX_COPY_IPV6((struct prefix_ipv6 *)&p, CONNECTED_PREFIX(ifc));
718e3744 443
d62a17ae 444 /* Apply mask to the network. */
445 apply_mask(&p);
718e3744 446
1cbb5dfc 447#ifndef LINUX
d62a17ae 448 /* XXX: It is already done by rib_bogus_ipv6 within rib_add */
449 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
450 return;
726f9b2b 451#endif
718e3744 452
d62a17ae 453 rib_add(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0,
fd36be7e 454 &p, NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0);
718e3744 455
d62a17ae 456 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
457 zlog_debug(
458 "%u: IF %s IPv6 address down, scheduling RIB processing",
459 ifp->vrf_id, ifp->name);
b84c7253 460
d62a17ae 461 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
40c7bdb0 462
d62a17ae 463 /* Schedule LSP forwarding entries for processing, if appropriate. */
464 if (ifp->vrf_id == VRF_DEFAULT) {
465 if (IS_ZEBRA_DEBUG_MPLS)
466 zlog_debug(
467 "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
468 ifp->vrf_id, ifp->name);
469 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
470 }
718e3744 471}
472
473/* Add connected IPv6 route to the interface. */
d62a17ae 474void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
608105a7 475 u_char prefixlen, const char *label)
718e3744 476{
d62a17ae 477 struct prefix_ipv6 *p;
478 struct connected *ifc;
479
480 if (ipv6_martian(addr))
481 return;
482
483 /* Make connected structure. */
484 ifc = connected_new();
485 ifc->ifp = ifp;
486 ifc->flags = flags;
487 /* If we get a notification from the kernel,
488 * we can safely assume the address is known to the kernel */
489 SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
490
491 /* Allocate new connected address. */
492 p = prefix_ipv6_new();
493 p->family = AF_INET6;
494 IPV6_ADDR_COPY(&p->prefix, addr);
495 p->prefixlen = prefixlen;
496 ifc->address = (struct prefix *)p;
497
d62a17ae 498 /* Label of this address. */
499 if (label)
500 ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
501
502 /* On Linux, we only get here when DAD is complete, therefore we can set
503 * ZEBRA_IFC_REAL.
504 *
505 * On BSD, there currently doesn't seem to be a way to check for
506 * completion of
507 * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL,
508 * although DAD
509 * might still be running.
510 */
511 SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
512 connected_update(ifp, ifc);
718e3744 513}
514
d62a17ae 515void connected_down_ipv6(struct interface *ifp, struct connected *ifc)
718e3744 516{
d62a17ae 517 struct prefix p;
fd36be7e
DL
518 struct nexthop nh = {
519 .type = NEXTHOP_TYPE_IFINDEX,
520 .ifindex = ifp->ifindex,
521 };
718e3744 522
d62a17ae 523 if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
524 return;
718e3744 525
d62a17ae 526 PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
718e3744 527
d62a17ae 528 apply_mask(&p);
718e3744 529
d62a17ae 530 if (IN6_IS_ADDR_UNSPECIFIED(&p.u.prefix6))
531 return;
718e3744 532
d62a17ae 533 rib_delete(AFI_IP6, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
fd36be7e 534 0, &p, NULL, &nh, 0, 0);
718e3744 535
d62a17ae 536 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
537 zlog_debug(
538 "%u: IF %s IPv6 address down, scheduling RIB processing",
539 ifp->vrf_id, ifp->name);
b84c7253 540
d62a17ae 541 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
40c7bdb0 542
d62a17ae 543 /* Schedule LSP forwarding entries for processing, if appropriate. */
544 if (ifp->vrf_id == VRF_DEFAULT) {
545 if (IS_ZEBRA_DEBUG_MPLS)
546 zlog_debug(
547 "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
548 ifp->vrf_id, ifp->name);
549 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
550 }
718e3744 551}
552
d62a17ae 553void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
608105a7 554 u_char prefixlen)
718e3744 555{
d62a17ae 556 struct prefix_ipv6 p;
557 struct connected *ifc;
558
559 memset(&p, 0, sizeof(struct prefix_ipv6));
560 p.family = AF_INET6;
561 memcpy(&p.prefix, address, sizeof(struct in6_addr));
562 p.prefixlen = prefixlen;
563
564 ifc = connected_check(ifp, (struct prefix *)&p);
565 if (!ifc)
566 return;
567
568 connected_withdraw(ifc);
569
570 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
571 zlog_debug(
572 "%u: IF %s IPv6 address del, scheduling RIB processing",
573 ifp->vrf_id, ifp->name);
574
575 rib_update(ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
576
577 /* Schedule LSP forwarding entries for processing, if appropriate. */
578 if (ifp->vrf_id == VRF_DEFAULT) {
579 if (IS_ZEBRA_DEBUG_MPLS)
580 zlog_debug(
581 "%u: IF %s IPv4 address add/up, scheduling MPLS processing",
582 ifp->vrf_id, ifp->name);
583 mpls_mark_lsps_for_processing(vrf_info_lookup(ifp->vrf_id));
584 }
718e3744 585}
d44ca835 586
d62a17ae 587int connected_is_unnumbered(struct interface *ifp)
d44ca835 588{
d62a17ae 589 struct connected *connected;
590 struct listnode *node;
591
592 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) {
593 if (CHECK_FLAG(connected->conf, ZEBRA_IFC_REAL)
594 && connected->address->family == AF_INET)
595 return CHECK_FLAG(connected->flags,
596 ZEBRA_IFA_UNNUMBERED);
597 }
598 return 0;
d44ca835 599}