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