]> git.proxmox.com Git - mirror_frr.git/blame - lib/if.c
*: Refactor ifindex2ifname to be VRF aware
[mirror_frr.git] / lib / if.c
CommitLineData
106d2fd5 1
718e3744 2/*
3 * Interface functions.
4 * Copyright (C) 1997, 98 Kunihiro Ishiguro
5 *
6 * This file is part of GNU Zebra.
7 *
8 * GNU Zebra is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundation; either version 2, or (at your
11 * option) any later version.
12 *
13 * GNU Zebra is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GNU Zebra; see the file COPYING. If not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24#include <zebra.h>
25
26#include "linklist.h"
27#include "vector.h"
28#include "vty.h"
29#include "command.h"
8736158a 30#include "vrf.h"
718e3744 31#include "if.h"
32#include "sockunion.h"
33#include "prefix.h"
718e3744 34#include "memory.h"
35#include "table.h"
36#include "buffer.h"
718e3744 37#include "log.h"
6b0655a2 38
4a1ab8e4
DL
39DEFINE_MTYPE( LIB, IF, "Interface")
40DEFINE_MTYPE_STATIC(LIB, CONNECTED, "Connected")
41DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected")
42DEFINE_MTYPE( LIB, CONNECTED_LABEL, "Connected interface label")
43DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters")
44
e80e7cce
DL
45DEFINE_QOBJ_TYPE(interface)
46
8736158a 47/* List of interfaces in only the default VRF */
244c1cdc 48int ptm_enable = 0;
718e3744 49
50/* One for each program. This structure is needed to store hooks. */
51struct if_master
52{
53 int (*if_new_hook) (struct interface *);
54 int (*if_delete_hook) (struct interface *);
8736158a 55} if_master = {0,};
6b0655a2 56
3a0391a9 57/* Compare interface names, returning an integer greater than, equal to, or
58 * less than 0, (following the strcmp convention), according to the
59 * relationship between ifp1 and ifp2. Interface names consist of an
60 * alphabetic prefix and a numeric suffix. The primary sort key is
61 * lexicographic by name, and then numeric by number. No number sorts
62 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
63 * devpty0, de0 < del0
64 */
106d2fd5 65int
974fc9d2 66if_cmp_name_func (char *p1, char *p2)
106d2fd5 67{
68 unsigned int l1, l2;
69 long int x1, x2;
106d2fd5 70 int res;
71
90578521 72 while (*p1 && *p2) {
106d2fd5 73 /* look up to any number */
74 l1 = strcspn(p1, "0123456789");
75 l2 = strcspn(p2, "0123456789");
76
77 /* name lengths are different -> compare names */
78 if (l1 != l2)
79 return (strcmp(p1, p2));
80
3a0391a9 81 /* Note that this relies on all numbers being less than all letters, so
82 * that de0 < del0.
83 */
106d2fd5 84 res = strncmp(p1, p2, l1);
85
86 /* names are different -> compare them */
87 if (res)
88 return res;
89
90 /* with identical name part, go to numeric part */
106d2fd5 91 p1 += l1;
92 p2 += l1;
93
b06c14f2 94 if (!*p1)
95 return -1;
96 if (!*p2)
97 return 1;
98
106d2fd5 99 x1 = strtol(p1, &p1, 10);
100 x2 = strtol(p2, &p2, 10);
101
102 /* let's compare numbers now */
103 if (x1 < x2)
104 return -1;
105 if (x1 > x2)
106 return 1;
107
108 /* numbers were equal, lets do it again..
109 (it happens with name like "eth123.456:789") */
110 }
90578521 111 if (*p1)
112 return 1;
113 if (*p2)
114 return -1;
115 return 0;
106d2fd5 116}
117
974fc9d2
DS
118static int
119if_cmp_func (struct interface *ifp1, struct interface *ifp2)
120{
121 return if_cmp_name_func (ifp1->name, ifp2->name);
122}
123
718e3744 124/* Create new interface structure. */
718e3744 125struct interface *
4e5266b8 126if_create (const char *name, int namelen, vrf_id_t vrf_id)
718e3744 127{
128 struct interface *ifp;
8736158a 129 struct list *intf_list = vrf_iflist_get (vrf_id);
718e3744 130
d2fc8896 131 ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
132 ifp->ifindex = IFINDEX_INTERNAL;
718e3744 133
106d2fd5 134 assert (name);
d2fc8896 135 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
106d2fd5 136 strncpy (ifp->name, name, namelen);
d2fc8896 137 ifp->name[namelen] = '\0';
8736158a 138 ifp->vrf_id = vrf_id;
1306c09a 139 if (if_lookup_by_name (ifp->name, vrf_id) == NULL)
8736158a 140 listnode_add_sort (intf_list, ifp);
d2fc8896 141 else
142 zlog_err("if_create(%s): corruption detected -- interface with this "
8736158a 143 "name exists already in VRF %u!", ifp->name, vrf_id);
718e3744 144 ifp->connected = list_new ();
145 ifp->connected->del = (void (*) (void *)) connected_free;
146
a80beece
DS
147 ifp->nbr_connected = list_new ();
148 ifp->nbr_connected->del = (void (*) (void *)) nbr_connected_free;
149
c9506a0a
DS
150 /* Enable Link-detection by default */
151 SET_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION);
152
e80e7cce
DL
153 QOBJ_REG (ifp, interface);
154
718e3744 155 if (if_master.if_new_hook)
156 (*if_master.if_new_hook) (ifp);
157
158 return ifp;
159}
160
f93e3f69
DS
161/* Create new interface structure. */
162void
163if_update_vrf (struct interface *ifp, const char *name, int namelen, vrf_id_t vrf_id)
164{
165 struct list *intf_list = vrf_iflist_get (vrf_id);
166
167 /* remove interface from old master vrf list */
168 if (vrf_iflist (ifp->vrf_id))
169 listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
170
171 assert (name);
172 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
173 strncpy (ifp->name, name, namelen);
174 ifp->name[namelen] = '\0';
175 ifp->vrf_id = vrf_id;
1306c09a 176 if (if_lookup_by_name (ifp->name, vrf_id) == NULL)
f93e3f69
DS
177 listnode_add_sort (intf_list, ifp);
178 else
179 zlog_err("if_create(%s): corruption detected -- interface with this "
180 "name exists already in VRF %u!", ifp->name, vrf_id);
181
182 return;
183}
184
185
d2fc8896 186/* Delete interface structure. */
718e3744 187void
d2fc8896 188if_delete_retain (struct interface *ifp)
718e3744 189{
718e3744 190 if (if_master.if_delete_hook)
191 (*if_master.if_delete_hook) (ifp);
192
e80e7cce
DL
193 QOBJ_UNREG (ifp);
194
718e3744 195 /* Free connected address list */
2dd04c5d 196 list_delete_all_node (ifp->connected);
a80beece
DS
197
198 /* Free connected nbr address list */
199 list_delete_all_node (ifp->nbr_connected);
d2fc8896 200}
201
202/* Delete and free interface structure. */
203void
204if_delete (struct interface *ifp)
205{
8736158a 206 listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
d2fc8896 207
208 if_delete_retain(ifp);
718e3744 209
2dd04c5d 210 list_free (ifp->connected);
a80beece 211 list_free (ifp->nbr_connected);
2dd04c5d 212
16f1b9ee
OD
213 if_link_params_free (ifp);
214
718e3744 215 XFREE (MTYPE_IF, ifp);
216}
217
218/* Add hook to interface master. */
219void
220if_add_hook (int type, int (*func)(struct interface *ifp))
221{
222 switch (type) {
223 case IF_NEW_HOOK:
224 if_master.if_new_hook = func;
225 break;
226 case IF_DELETE_HOOK:
227 if_master.if_delete_hook = func;
228 break;
229 default:
230 break;
231 }
232}
233
234/* Interface existance check by index. */
235struct interface *
7e2b7603 236if_lookup_by_index (ifindex_t ifindex, vrf_id_t vrf_id)
718e3744 237{
52dc7ee6 238 struct listnode *node;
718e3744 239 struct interface *ifp;
240
8736158a 241 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 242 {
b892f1dd 243 if (ifp->ifindex == ifindex)
718e3744 244 return ifp;
245 }
246 return NULL;
247}
248
8cc4198f 249const char *
baaea325 250ifindex2ifname (ifindex_t ifindex, vrf_id_t vrf_id)
718e3744 251{
718e3744 252 struct interface *ifp;
253
7e2b7603 254 return ((ifp = if_lookup_by_index (ifindex, vrf_id)) != NULL) ?
8cc4198f 255 ifp->name : "unknown";
d2fc8896 256}
257
b892f1dd 258ifindex_t
8736158a 259ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
d2fc8896 260{
261 struct interface *ifp;
262
1306c09a 263 return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp->ifindex
3e4ee959 264 : IFINDEX_INTERNAL;
718e3744 265}
266
b892f1dd 267ifindex_t
8736158a
FL
268ifname2ifindex (const char *name)
269{
270 return ifname2ifindex_vrf (name, VRF_DEFAULT);
271}
272
718e3744 273/* Interface existance check by interface name. */
274struct interface *
1306c09a 275if_lookup_by_name (const char *name, vrf_id_t vrf_id)
718e3744 276{
52dc7ee6 277 struct listnode *node;
718e3744 278 struct interface *ifp;
3e4ee959
PJ
279
280 if (name)
8736158a 281 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
3e4ee959
PJ
282 {
283 if (strcmp(name, ifp->name) == 0)
284 return ifp;
285 }
718e3744 286 return NULL;
287}
288
f8962871
DS
289struct interface *
290if_lookup_by_name_all_vrf (const char *name)
291{
1a1a7065 292 struct vrf *vrf;
f8962871 293 struct interface *ifp;
f8962871 294
1a1a7065 295 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
f8962871 296 {
1306c09a 297 ifp = if_lookup_by_name (name, vrf->vrf_id);
f8962871
DS
298 if (ifp)
299 return ifp;
300 }
301
302 return NULL;
303}
304
8736158a 305struct interface *
fa787f91 306if_lookup_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id)
a349198f 307{
308 struct listnode *node;
1eb8ef25 309 struct interface *ifp;
a349198f 310
311 if (namelen > INTERFACE_NAMSIZ)
312 return NULL;
313
8736158a 314 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
a349198f 315 {
a349198f 316 if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
317 return ifp;
318 }
319 return NULL;
320}
321
718e3744 322/* Lookup interface by IPv4 address. */
323struct interface *
c5e2cb11 324if_lookup_exact_address (void *src, int family, vrf_id_t vrf_id)
718e3744 325{
52dc7ee6 326 struct listnode *node;
327 struct listnode *cnode;
718e3744 328 struct interface *ifp;
329 struct prefix *p;
330 struct connected *c;
331
8736158a 332 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 333 {
1eb8ef25 334 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
718e3744 335 {
718e3744 336 p = c->address;
337
0aabccc0 338 if (p && (p->family == family))
718e3744 339 {
0aabccc0
DD
340 if (family == AF_INET)
341 {
342 if (IPV4_ADDR_SAME (&p->u.prefix4, (struct in_addr *)src))
343 return ifp;
344 }
345 else if (family == AF_INET6)
346 {
0527bd80 347 if (IPV6_ADDR_SAME (&p->u.prefix6, (struct in6_addr *)src))
0aabccc0
DD
348 return ifp;
349 }
350 }
718e3744 351 }
352 }
353 return NULL;
354}
355
356/* Lookup interface by IPv4 address. */
b10ce841 357struct connected *
95af5f13 358if_lookup_address (void *matchaddr, int family, vrf_id_t vrf_id)
718e3744 359{
52dc7ee6 360 struct listnode *node;
718e3744 361 struct prefix addr;
3fb9cd6e 362 int bestlen = 0;
52dc7ee6 363 struct listnode *cnode;
718e3744 364 struct interface *ifp;
718e3744 365 struct connected *c;
b10ce841 366 struct connected *match;
718e3744 367
0aabccc0
DD
368 if (family == AF_INET)
369 {
370 addr.family = AF_INET;
371 addr.u.prefix4 = *((struct in_addr *)matchaddr);
372 addr.prefixlen = IPV4_MAX_BITLEN;
373 }
374 else if (family == AF_INET6)
375 {
376 addr.family = AF_INET6;
377 addr.u.prefix6 = *((struct in6_addr *)matchaddr);
378 addr.prefixlen = IPV6_MAX_BITLEN;
379 }
718e3744 380
381 match = NULL;
382
8736158a 383 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 384 {
1eb8ef25 385 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
718e3744 386 {
e4529636
AS
387 if (c->address && (c->address->family == AF_INET) &&
388 prefix_match(CONNECTED_PREFIX(c), &addr) &&
389 (c->address->prefixlen > bestlen))
718e3744 390 {
e4529636 391 bestlen = c->address->prefixlen;
b10ce841 392 match = c;
718e3744 393 }
394 }
395 }
396 return match;
397}
398
b81e97a8
DD
399/* Lookup interface by prefix */
400struct interface *
a90607a4 401if_lookup_prefix (struct prefix *prefix, vrf_id_t vrf_id)
b81e97a8
DD
402{
403 struct listnode *node;
b81e97a8
DD
404 struct listnode *cnode;
405 struct interface *ifp;
406 struct connected *c;
407
8736158a 408 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
b81e97a8
DD
409 {
410 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
411 {
412 if (prefix_cmp(c->address, prefix) == 0)
413 {
414 return ifp;
415 }
416 }
417 }
418 return NULL;
419}
420
718e3744 421/* Get interface by name if given name interface doesn't exist create
422 one. */
423struct interface *
92a57eb2 424if_get_by_name (const char *name, vrf_id_t vrf_id)
718e3744 425{
426 struct interface *ifp;
427
1306c09a 428 return ((ifp = if_lookup_by_name (name, vrf_id)) != NULL) ? ifp :
4e5266b8 429 if_create (name, strlen(name), vrf_id);
a349198f 430}
431
8736158a 432struct interface *
07a112a1 433if_get_by_name_len (const char *name, size_t namelen, vrf_id_t vrf_id, int vty)
a349198f 434{
435 struct interface *ifp;
1a1a7065 436 struct vrf *vrf;
85f9da7f 437 struct listnode *node;
85f9da7f 438
fa787f91 439 ifp = if_lookup_by_name_len (name, namelen, vrf_id);
85f9da7f
DS
440 if (ifp)
441 return ifp;
a349198f 442
85f9da7f 443 /* Didn't find the interface on that vrf. Defined on a different one? */
1a1a7065 444 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
85f9da7f 445 {
85f9da7f
DS
446 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf->vrf_id), node, ifp))
447 {
448 if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
449 {
450 /* Found a match. If the interface command was entered in vty without a
451 * VRF (passed as VRF_DEFAULT), accept the ifp we found. If a vrf was
452 * entered and there is a mismatch, reject it if from vty. If it came
453 * from the kernel by way of zclient, believe it and update
454 * the ifp accordingly.
455 */
53eadacf 456 if (vty)
457 {
458 if (vrf_id == VRF_DEFAULT)
459 return ifp;
460 return NULL;
461 }
85f9da7f
DS
462 else
463 {
464 if_update_vrf (ifp, name, namelen, vrf_id);
465 return ifp;
466 }
467 }
468 }
469 }
4e5266b8 470 return (if_create (name, namelen, vrf_id));
8736158a
FL
471}
472
718e3744 473/* Does interface up ? */
474int
475if_is_up (struct interface *ifp)
476{
477 return ifp->flags & IFF_UP;
478}
479
2e3b2e47 480/* Is interface running? */
481int
482if_is_running (struct interface *ifp)
483{
484 return ifp->flags & IFF_RUNNING;
485}
486
487/* Is the interface operative, eg. either UP & RUNNING
244c1cdc
DS
488 or UP & !ZEBRA_INTERFACE_LINK_DETECTION and
489 if ptm checking is enabled, then ptm check has passed */
2e3b2e47 490int
491if_is_operative (struct interface *ifp)
492{
493 return ((ifp->flags & IFF_UP) &&
244c1cdc
DS
494 (((ifp->flags & IFF_RUNNING) &&
495 (ifp->ptm_status || !ifp->ptm_enable)) ||
496 !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
497}
498
499/* Is the interface operative, eg. either UP & RUNNING
500 or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */
501int
502if_is_no_ptm_operative (struct interface *ifp)
503{
504 return ((ifp->flags & IFF_UP) &&
505 ((ifp->flags & IFF_RUNNING) ||
506 !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
2e3b2e47 507}
508
718e3744 509/* Is this loopback interface ? */
510int
511if_is_loopback (struct interface *ifp)
512{
4ba9b924 513 /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
514 * but Y on platform N?
515 */
516 return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
718e3744 517}
518
519/* Does this interface support broadcast ? */
520int
521if_is_broadcast (struct interface *ifp)
522{
523 return ifp->flags & IFF_BROADCAST;
524}
525
526/* Does this interface support broadcast ? */
527int
528if_is_pointopoint (struct interface *ifp)
529{
530 return ifp->flags & IFF_POINTOPOINT;
531}
532
533/* Does this interface support multicast ? */
534int
535if_is_multicast (struct interface *ifp)
536{
537 return ifp->flags & IFF_MULTICAST;
538}
539
540/* Printout flag information into log */
541const char *
542if_flag_dump (unsigned long flag)
543{
544 int separator = 0;
545 static char logbuf[BUFSIZ];
546
547#define IFF_OUT_LOG(X,STR) \
4ba9b924 548 if (flag & (X)) \
718e3744 549 { \
550 if (separator) \
551 strlcat (logbuf, ",", BUFSIZ); \
552 else \
553 separator = 1; \
554 strlcat (logbuf, STR, BUFSIZ); \
555 }
556
630c97ce 557 strlcpy (logbuf, "<", BUFSIZ);
718e3744 558 IFF_OUT_LOG (IFF_UP, "UP");
559 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
560 IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
561 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
562 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
563 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
564 IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
565 IFF_OUT_LOG (IFF_NOARP, "NOARP");
566 IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
567 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
568 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
569 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
570 IFF_OUT_LOG (IFF_LINK0, "LINK0");
571 IFF_OUT_LOG (IFF_LINK1, "LINK1");
572 IFF_OUT_LOG (IFF_LINK2, "LINK2");
573 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
4ba9b924 574 IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
575 IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
576 IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
577 IFF_OUT_LOG (IFF_IPV4, "IPv4");
578 IFF_OUT_LOG (IFF_IPV6, "IPv6");
718e3744 579
580 strlcat (logbuf, ">", BUFSIZ);
581
582 return logbuf;
630c97ce 583#undef IFF_OUT_LOG
718e3744 584}
585
586/* For debugging */
8cc4198f 587static void
cedd7f2f 588if_dump (const struct interface *ifp)
718e3744 589{
1f9a9fff
PJ
590 struct listnode *node;
591 struct connected *c __attribute__((unused));
592
593 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
3968dbf8 594 zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
1f9a9fff 595 "mtu6 %d %s",
3968dbf8 596 ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
1f9a9fff 597 ifp->mtu6, if_flag_dump (ifp->flags));
718e3744 598}
599
600/* Interface printing for all interface. */
601void
66e5cd87 602if_dump_all (void)
718e3744 603{
1a1a7065 604 struct vrf *vrf;
52dc7ee6 605 struct listnode *node;
1eb8ef25 606 void *p;
718e3744 607
1a1a7065
RW
608 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
609 if (vrf->iflist != NULL)
610 for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, p))
8736158a 611 if_dump (p);
718e3744 612}
613
6147e2c6 614DEFUN (interface_desc,
718e3744 615 interface_desc_cmd,
fcbee690 616 "description LINE...",
718e3744 617 "Interface specific description\n"
618 "Characters describing this interface\n")
619{
58749582 620 int idx_line = 1;
be301cc2 621 VTY_DECLVAR_CONTEXT (interface, ifp);
718e3744 622
718e3744 623 if (ifp->desc)
3b8b1855 624 XFREE (MTYPE_TMP, ifp->desc);
58749582 625 ifp->desc = argv_concat(argv, argc, idx_line);
718e3744 626
627 return CMD_SUCCESS;
628}
629
6147e2c6 630DEFUN (no_interface_desc,
718e3744 631 no_interface_desc_cmd,
632 "no description",
633 NO_STR
634 "Interface specific description\n")
635{
be301cc2 636 VTY_DECLVAR_CONTEXT (interface, ifp);
718e3744 637
718e3744 638 if (ifp->desc)
0241684e 639 XFREE (MTYPE_TMP, ifp->desc);
718e3744 640 ifp->desc = NULL;
641
642 return CMD_SUCCESS;
643}
6b0655a2 644
98954844
PJ
645#ifdef SUNOS_5
646/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
647 * a seperate struct interface for each logical interface, so config
648 * file may be full of 'interface fooX:Y'. Solaris however does not
649 * expose logical interfaces via PF_ROUTE, so trying to track logical
650 * interfaces can be fruitless, for that reason Quagga only tracks
651 * the primary IP interface.
652 *
653 * We try accomodate SUNWzebra by:
654 * - looking up the interface name, to see whether it exists, if so
655 * its useable
656 * - for protocol daemons, this could only because zebra told us of
657 * the interface
658 * - for zebra, only because it learnt from kernel
659 * - if not:
660 * - search the name to see if it contains a sub-ipif / logical interface
661 * seperator, the ':' char. If it does:
662 * - text up to that char must be the primary name - get that name.
663 * if not:
664 * - no idea, just get the name in its entirety.
665 */
666static struct interface *
8736158a 667if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
98954844
PJ
668{
669 struct interface *ifp;
670 size_t seppos = 0;
718e3744 671
fa787f91 672 if ( (ifp = if_lookup_by_name_len (name, nlen, vrf_id)) != NULL)
98954844
PJ
673 return ifp;
674
675 /* hunt the primary interface name... */
676 while (seppos < nlen && name[seppos] != ':')
677 seppos++;
678
679 /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
680 if (seppos < nlen)
07a112a1 681 return if_get_by_name_len (name, seppos, vrf_id, 1);
98954844 682 else
07a112a1 683 return if_get_by_name_len (name, nlen, vrf_id, 1);
98954844
PJ
684}
685#endif /* SUNOS_5 */
6b0655a2 686
718e3744 687DEFUN (interface,
688 interface_cmd,
199d90a1 689 "interface IFNAME [vrf NAME]",
718e3744 690 "Select an interface to configure\n"
fcbee690
QY
691 "Interface's name\n"
692 VRF_CMD_HELP_STR)
718e3744 693{
c349116d 694 int idx_ifname = 1;
abddf075 695 int idx_vrf = 3;
c349116d 696 const char *ifname = argv[idx_ifname]->arg;
abddf075 697 const char *vrfname = (argc > 2) ? argv[idx_vrf]->arg : NULL;
fcbee690 698
718e3744 699 struct interface *ifp;
d2fc8896 700 size_t sl;
8736158a 701 vrf_id_t vrf_id = VRF_DEFAULT;
d2fc8896 702
fcbee690 703 if ((sl = strlen(ifname)) > INTERFACE_NAMSIZ)
d2fc8896 704 {
705 vty_out (vty, "%% Interface name %s is invalid: length exceeds "
706 "%d characters%s",
fcbee690 707 ifname, INTERFACE_NAMSIZ, VTY_NEWLINE);
d2fc8896 708 return CMD_WARNING;
709 }
718e3744 710
f93e3f69
DS
711/*Pending: need proper vrf name based lookup/(possible creation of VRF)
712 Imagine forward reference of a vrf by name in this interface config */
fcbee690
QY
713 if (vrfname)
714 VRF_GET_ID (vrf_id, vrfname);
cd2a8a42 715
98954844 716#ifdef SUNOS_5
fcbee690 717 ifp = if_sunwzebra_get (ifname, sl, vrf_id);
98954844 718#else
07a112a1 719 ifp = if_get_by_name_len (ifname, sl, vrf_id, 1);
98954844 720#endif /* SUNOS_5 */
718e3744 721
85f9da7f
DS
722 if (!ifp)
723 {
fcbee690 724 vty_out (vty, "%% interface %s not in %s%s", ifname, vrfname, VTY_NEWLINE);
85f9da7f
DS
725 return CMD_WARNING;
726 }
a50b7ceb 727 VTY_PUSH_CONTEXT (INTERFACE_NODE, ifp);
718e3744 728
729 return CMD_SUCCESS;
730}
731
32d2463c 732DEFUN_NOSH (no_interface,
733 no_interface_cmd,
199d90a1 734 "no interface IFNAME [vrf NAME]",
32d2463c 735 NO_STR
736 "Delete a pseudo interface's configuration\n"
fcbee690
QY
737 "Interface's name\n"
738 VRF_CMD_HELP_STR)
32d2463c 739{
fcbee690
QY
740 const char *ifname = argv[2]->arg;
741 const char *vrfname = (argc > 3) ? argv[3]->arg : NULL;
742
32d2463c 743 // deleting interface
744 struct interface *ifp;
8736158a 745 vrf_id_t vrf_id = VRF_DEFAULT;
32d2463c 746
fcbee690
QY
747 if (argc > 3)
748 VRF_GET_ID (vrf_id, vrfname);
cd2a8a42 749
1306c09a 750 ifp = if_lookup_by_name (ifname, vrf_id);
32d2463c 751
752 if (ifp == NULL)
d2fc8896 753 {
fcbee690 754 vty_out (vty, "%% Interface %s does not exist%s", ifname, VTY_NEWLINE);
d2fc8896 755 return CMD_WARNING;
756 }
32d2463c 757
bfc13532 758 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
d2fc8896 759 {
760 vty_out (vty, "%% Only inactive interfaces can be deleted%s",
761 VTY_NEWLINE);
762 return CMD_WARNING;
763 }
32d2463c 764
765 if_delete(ifp);
766
767 return CMD_SUCCESS;
768}
769
0b84f294
DL
770void
771if_cmd_init (void)
772{
773 install_element (CONFIG_NODE, &interface_cmd);
774 install_element (CONFIG_NODE, &no_interface_cmd);
775
776 install_default (INTERFACE_NODE);
777 install_element (INTERFACE_NODE, &interface_desc_cmd);
778 install_element (INTERFACE_NODE, &no_interface_desc_cmd);
779}
780
d7d73ffc 781#if 0
718e3744 782/* For debug purpose. */
783DEFUN (show_address,
784 show_address_cmd,
199d90a1 785 "show address [vrf NAME]",
718e3744 786 SHOW_STR
fcbee690
QY
787 "address\n"
788 VRF_CMD_HELP_STR)
718e3744 789{
abddf075 790 int idx_vrf = 3;
52dc7ee6 791 struct listnode *node;
792 struct listnode *node2;
718e3744 793 struct interface *ifp;
794 struct connected *ifc;
795 struct prefix *p;
8736158a 796 vrf_id_t vrf_id = VRF_DEFAULT;
718e3744 797
fcbee690 798 if (argc > 2)
58749582 799 VRF_GET_ID (vrf_id, argv[idx_vrf]->arg);
8736158a
FL
800
801 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
718e3744 802 {
1eb8ef25 803 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
718e3744 804 {
718e3744 805 p = ifc->address;
806
807 if (p->family == AF_INET)
808 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
809 VTY_NEWLINE);
810 }
811 }
812 return CMD_SUCCESS;
813}
814
8736158a
FL
815DEFUN (show_address_vrf_all,
816 show_address_vrf_all_cmd,
9ccf14f7 817 "show address vrf all",
8736158a
FL
818 SHOW_STR
819 "address\n"
820 VRF_ALL_CMD_HELP_STR)
821{
1a1a7065 822 struct vrf *vrf;
8736158a
FL
823 struct listnode *node;
824 struct listnode *node2;
825 struct interface *ifp;
826 struct connected *ifc;
827 struct prefix *p;
8736158a 828
a62c4901 829 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
8736158a 830 {
1a1a7065 831 if (!vrf->iflist || !listcount (vrf->iflist))
8736158a
FL
832 continue;
833
1a1a7065
RW
834 vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf->vrf_id, VTY_NEWLINE,
835 VTY_NEWLINE);
8736158a 836
1a1a7065 837 for (ALL_LIST_ELEMENTS_RO (vrf->iflist, node, ifp))
8736158a
FL
838 {
839 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
840 {
841 p = ifc->address;
842
843 if (p->family == AF_INET)
844 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
845 VTY_NEWLINE);
846 }
847 }
848 }
849 return CMD_SUCCESS;
850}
d7d73ffc 851#endif
8736158a 852
718e3744 853/* Allocate connected structure. */
854struct connected *
8cc4198f 855connected_new (void)
718e3744 856{
393deb9b 857 return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
718e3744 858}
859
a80beece
DS
860/* Allocate nbr connected structure. */
861struct nbr_connected *
862nbr_connected_new (void)
863{
864 return XCALLOC (MTYPE_NBR_CONNECTED, sizeof (struct nbr_connected));
865}
866
718e3744 867/* Free connected structure. */
868void
869connected_free (struct connected *connected)
870{
871 if (connected->address)
872 prefix_free (connected->address);
873
874 if (connected->destination)
875 prefix_free (connected->destination);
876
877 if (connected->label)
9c4f1c6f 878 XFREE (MTYPE_CONNECTED_LABEL, connected->label);
718e3744 879
880 XFREE (MTYPE_CONNECTED, connected);
881}
882
a80beece
DS
883/* Free nbr connected structure. */
884void
885nbr_connected_free (struct nbr_connected *connected)
886{
887 if (connected->address)
888 prefix_free (connected->address);
889
890 XFREE (MTYPE_NBR_CONNECTED, connected);
891}
892
893/* If same interface nbr address already exists... */
894struct nbr_connected *
895nbr_connected_check (struct interface *ifp, struct prefix *p)
896{
897 struct nbr_connected *ifc;
898 struct listnode *node;
899
900 for (ALL_LIST_ELEMENTS_RO (ifp->nbr_connected, node, ifc))
901 if (prefix_same (ifc->address, p))
902 return ifc;
903
904 return NULL;
905}
906
718e3744 907/* Print if_addr structure. */
8cc4198f 908static void __attribute__ ((unused))
718e3744 909connected_log (struct connected *connected, char *str)
910{
911 struct prefix *p;
912 struct interface *ifp;
913 char logbuf[BUFSIZ];
914 char buf[BUFSIZ];
915
916 ifp = connected->ifp;
917 p = connected->address;
918
3968dbf8
FL
919 snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
920 str, ifp->name, ifp->vrf_id, prefix_family_str (p),
718e3744 921 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
922 p->prefixlen);
923
924 p = connected->destination;
925 if (p)
926 {
927 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
928 BUFSIZ - strlen(logbuf));
929 }
4525281a 930 zlog_info("%s", logbuf);
718e3744 931}
932
a80beece
DS
933/* Print if_addr structure. */
934static void __attribute__ ((unused))
935nbr_connected_log (struct nbr_connected *connected, char *str)
936{
937 struct prefix *p;
938 struct interface *ifp;
939 char logbuf[BUFSIZ];
940 char buf[BUFSIZ];
941
942 ifp = connected->ifp;
943 p = connected->address;
944
945 snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ",
946 str, ifp->name, prefix_family_str (p),
947 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
948 p->prefixlen);
949
4525281a 950 zlog_info("%s", logbuf);
a80beece
DS
951}
952
718e3744 953/* If two connected address has same prefix return 1. */
8cc4198f 954static int
718e3744 955connected_same_prefix (struct prefix *p1, struct prefix *p2)
956{
957 if (p1->family == p2->family)
958 {
959 if (p1->family == AF_INET &&
960 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
961 return 1;
718e3744 962 if (p1->family == AF_INET6 &&
963 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
964 return 1;
718e3744 965 }
966 return 0;
967}
968
38485402
DS
969struct connected *
970connected_lookup_prefix_exact (struct interface *ifp, struct prefix *p)
971{
972 struct listnode *node;
973 struct listnode *next;
974 struct connected *ifc;
975
976 for (node = listhead (ifp->connected); node; node = next)
977 {
978 ifc = listgetdata (node);
979 next = node->next;
980
981 if (connected_same_prefix (ifc->address, p))
982 return ifc;
983 }
984 return NULL;
985}
986
718e3744 987struct connected *
988connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
989{
990 struct listnode *node;
991 struct listnode *next;
992 struct connected *ifc;
993
994 /* In case of same prefix come, replace it with new one. */
995 for (node = listhead (ifp->connected); node; node = next)
996 {
1eb8ef25 997 ifc = listgetdata (node);
718e3744 998 next = node->next;
999
1000 if (connected_same_prefix (ifc->address, p))
1001 {
1002 listnode_delete (ifp->connected, ifc);
1003 return ifc;
1004 }
1005 }
1006 return NULL;
1007}
1008
bd40c341 1009/* Find the address on our side that will be used when packets
727d104b 1010 are sent to dst. */
1011struct connected *
bd40c341 1012connected_lookup_prefix (struct interface *ifp, struct prefix *addr)
727d104b 1013{
52dc7ee6 1014 struct listnode *cnode;
727d104b 1015 struct connected *c;
1016 struct connected *match;
1017
727d104b 1018 match = NULL;
1019
1eb8ef25 1020 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
727d104b 1021 {
bd40c341
DS
1022 if (c->address && (c->address->family == addr->family) &&
1023 prefix_match(CONNECTED_PREFIX(c), addr) &&
e4529636
AS
1024 (!match || (c->address->prefixlen > match->address->prefixlen)))
1025 match = c;
727d104b 1026 }
1027 return match;
1028}
1029
4a7aac1b 1030struct connected *
1031connected_add_by_prefix (struct interface *ifp, struct prefix *p,
1032 struct prefix *destination)
1033{
1034 struct connected *ifc;
1035
1036 /* Allocate new connected address. */
1037 ifc = connected_new ();
1038 ifc->ifp = ifp;
1039
1040 /* Fetch interface address */
1041 ifc->address = prefix_new();
1042 memcpy (ifc->address, p, sizeof(struct prefix));
1043
1044 /* Fetch dest address */
3fb9cd6e 1045 if (destination)
1046 {
1047 ifc->destination = prefix_new();
1048 memcpy (ifc->destination, destination, sizeof(struct prefix));
1049 }
4a7aac1b 1050
1051 /* Add connected address to the interface. */
1052 listnode_add (ifp->connected, ifc);
1053 return ifc;
1054}
1055
8cc4198f 1056#if 0 /* this route_table of struct connected's is unused
1057 * however, it would be good to use a route_table rather than
1058 * a list..
1059 */
718e3744 1060/* Interface looking up by interface's address. */
718e3744 1061/* Interface's IPv4 address reverse lookup table. */
1062struct route_table *ifaddr_ipv4_table;
1063/* struct route_table *ifaddr_ipv6_table; */
1064
8cc4198f 1065static void
718e3744 1066ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
1067{
1068 struct route_node *rn;
1069 struct prefix_ipv4 p;
1070
1071 p.family = AF_INET;
1072 p.prefixlen = IPV4_MAX_PREFIXLEN;
1073 p.prefix = *ifaddr;
1074
1075 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
1076 if (rn)
1077 {
1078 route_unlock_node (rn);
1079 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
1080 inet_ntoa (*ifaddr));
1081 return;
1082 }
1083 rn->info = ifp;
1084}
1085
8cc4198f 1086static void
718e3744 1087ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
1088{
1089 struct route_node *rn;
1090 struct prefix_ipv4 p;
1091
1092 p.family = AF_INET;
1093 p.prefixlen = IPV4_MAX_PREFIXLEN;
1094 p.prefix = *ifaddr;
1095
1096 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1097 if (! rn)
1098 {
1099 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
1100 inet_ntoa (*ifaddr));
1101 return;
1102 }
1103 rn->info = NULL;
1104 route_unlock_node (rn);
1105 route_unlock_node (rn);
1106}
1107
1108/* Lookup interface by interface's IP address or interface index. */
8cc4198f 1109static struct interface *
b892f1dd 1110ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
718e3744 1111{
1112 struct prefix_ipv4 p;
1113 struct route_node *rn;
1114 struct interface *ifp;
718e3744 1115
1116 if (addr)
1117 {
1118 p.family = AF_INET;
1119 p.prefixlen = IPV4_MAX_PREFIXLEN;
1120 p.prefix = *addr;
1121
1122 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1123 if (! rn)
1124 return NULL;
1125
1126 ifp = rn->info;
1127 route_unlock_node (rn);
1128 return ifp;
1129 }
1130 else
7e2b7603 1131 return if_lookup_by_index(ifindex, VRF_DEFAULT);
718e3744 1132}
8cc4198f 1133#endif /* ifaddr_ipv4_table */
718e3744 1134
1135/* Initialize interface list. */
1136void
b2d7c082 1137if_init (struct list **intf_list)
718e3744 1138{
8736158a 1139 *intf_list = list_new ();
8cc4198f 1140#if 0
718e3744 1141 ifaddr_ipv4_table = route_table_init ();
8cc4198f 1142#endif /* ifaddr_ipv4_table */
718e3744 1143
8736158a 1144 (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
718e3744 1145}
4bd045d5
TG
1146
1147void
b2d7c082 1148if_terminate (struct list **intf_list)
4bd045d5
TG
1149{
1150 for (;;)
1151 {
1152 struct interface *ifp;
1153
8736158a 1154 ifp = listnode_head (*intf_list);
4bd045d5
TG
1155 if (ifp == NULL)
1156 break;
1157
3f6d6a5d
DS
1158 if (ifp->node)
1159 {
1160 ifp->node->info = NULL;
1161 route_unlock_node (ifp->node);
1162 }
1163
4bd045d5
TG
1164 if_delete (ifp);
1165 }
1166
8736158a
FL
1167 list_delete (*intf_list);
1168 *intf_list = NULL;
4bd045d5 1169}
8ccc7e80
TT
1170
1171const char *
1172if_link_type_str (enum zebra_link_type llt)
1173{
1174 switch (llt)
1175 {
1176#define llts(T,S) case (T): return (S)
1177 llts(ZEBRA_LLT_UNKNOWN, "Unknown");
1178 llts(ZEBRA_LLT_ETHER, "Ethernet");
1179 llts(ZEBRA_LLT_EETHER, "Experimental Ethernet");
1180 llts(ZEBRA_LLT_AX25, "AX.25 Level 2");
1181 llts(ZEBRA_LLT_PRONET, "PROnet token ring");
1182 llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB");
1183 llts(ZEBRA_LLT_ARCNET, "ARCnet");
1184 llts(ZEBRA_LLT_APPLETLK, "AppleTalk");
1185 llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI");
1186 llts(ZEBRA_LLT_ATM, "ATM");
1187 llts(ZEBRA_LLT_METRICOM, "Metricom STRIP");
1188 llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4");
1189 llts(ZEBRA_LLT_EUI64, "EUI-64");
1190 llts(ZEBRA_LLT_INFINIBAND, "InfiniBand");
1191 llts(ZEBRA_LLT_SLIP, "SLIP");
1192 llts(ZEBRA_LLT_CSLIP, "Compressed SLIP");
1193 llts(ZEBRA_LLT_SLIP6, "SLIPv6");
1194 llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6");
1195 llts(ZEBRA_LLT_ROSE, "ROSE packet radio");
1196 llts(ZEBRA_LLT_X25, "CCITT X.25");
1197 llts(ZEBRA_LLT_PPP, "PPP");
1198 llts(ZEBRA_LLT_CHDLC, "Cisco HDLC");
1199 llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC");
1200 llts(ZEBRA_LLT_LAPB, "LAPB");
1201 llts(ZEBRA_LLT_IPIP, "IPIP Tunnel");
1202 llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel");
1203 llts(ZEBRA_LLT_FRAD, "FRAD");
1204 llts(ZEBRA_LLT_SKIP, "SKIP vif");
1205 llts(ZEBRA_LLT_LOOPBACK, "Loopback");
1206 llts(ZEBRA_LLT_LOCALTLK, "Localtalk");
1207 llts(ZEBRA_LLT_FDDI, "FDDI");
1208 llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT");
1209 llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel");
1210 llts(ZEBRA_LLT_IPGRE, "GRE over IP");
1211 llts(ZEBRA_LLT_PIMREG, "PIMSM registration");
1212 llts(ZEBRA_LLT_HIPPI, "HiPPI");
1213 llts(ZEBRA_LLT_IRDA, "IrDA");
1214 llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP");
1215 llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop");
1216 llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop");
1217 llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric");
1218 llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring");
1219 llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11");
1220 llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap");
1221 llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
1222 llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
1223 default:
1224 zlog_warn ("Unknown value %d", llt);
1225 return "Unknown type!";
1226#undef llts
1227 }
1228 return NULL;
1229}
16f1b9ee
OD
1230
1231struct if_link_params *
1232if_link_params_get (struct interface *ifp)
1233{
1234 int i;
1235
1236 if (ifp->link_params != NULL)
1237 return ifp->link_params;
1238
1239 struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS,
1240 sizeof (struct if_link_params));
1241 if (iflp == NULL) return NULL;
1242
daf0a4d2 1243 /* Set TE metric equal to standard metric */
16f1b9ee
OD
1244 iflp->te_metric = ifp->metric;
1245
1246 /* Compute default bandwidth based on interface */
b6a9e7b4
DS
1247 iflp->default_bw = ((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH)
1248 * TE_KILO_BIT / TE_BYTE);
16f1b9ee
OD
1249
1250 /* Set Max, Reservable and Unreserved Bandwidth */
b6a9e7b4
DS
1251 iflp->max_bw = iflp->default_bw;
1252 iflp->max_rsv_bw = iflp->default_bw;
16f1b9ee 1253 for (i = 0; i < MAX_CLASS_TYPE; i++)
b6a9e7b4 1254 iflp->unrsv_bw[i] = iflp->default_bw;
16f1b9ee
OD
1255
1256 /* Update Link parameters status */
daf0a4d2 1257 iflp->lp_status = LP_TE_METRIC | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
16f1b9ee
OD
1258
1259 /* Finally attach newly created Link Parameters */
1260 ifp->link_params = iflp;
1261
1262 return iflp;
1263}
1264
1265void
1266if_link_params_free (struct interface *ifp)
1267{
1268 if (ifp->link_params == NULL) return;
1269 XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
1270 ifp->link_params = NULL;
1271}