blob: 45c1accf0df2e33fae7ee129086b140468e67b56 [file] [log] [blame]
paul106d2fd2003-08-01 00:24:13 +00001
paul718e3742002-12-13 20:15:29 +00002/*
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"
Feng Lu5a5702f2015-05-22 11:39:59 +020030#include "vrf.h"
paul718e3742002-12-13 20:15:29 +000031#include "if.h"
32#include "sockunion.h"
33#include "prefix.h"
paul718e3742002-12-13 20:15:29 +000034#include "memory.h"
35#include "table.h"
36#include "buffer.h"
37#include "str.h"
38#include "log.h"
David Lamparter6b0655a2014-06-04 06:53:35 +020039
Feng Lu5a5702f2015-05-22 11:39:59 +020040/* List of interfaces in only the default VRF */
paul718e3742002-12-13 20:15:29 +000041struct list *iflist;
42
43/* One for each program. This structure is needed to store hooks. */
44struct if_master
45{
46 int (*if_new_hook) (struct interface *);
47 int (*if_delete_hook) (struct interface *);
Feng Lu5a5702f2015-05-22 11:39:59 +020048} if_master = {0,};
David Lamparter6b0655a2014-06-04 06:53:35 +020049
paul3a0391a2004-07-17 11:51:29 +000050/* Compare interface names, returning an integer greater than, equal to, or
51 * less than 0, (following the strcmp convention), according to the
52 * relationship between ifp1 and ifp2. Interface names consist of an
53 * alphabetic prefix and a numeric suffix. The primary sort key is
54 * lexicographic by name, and then numeric by number. No number sorts
55 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty <
56 * devpty0, de0 < del0
57 */
paul106d2fd2003-08-01 00:24:13 +000058int
59if_cmp_func (struct interface *ifp1, struct interface *ifp2)
60{
61 unsigned int l1, l2;
62 long int x1, x2;
63 char *p1, *p2;
64 int res;
65
66 p1 = ifp1->name;
67 p2 = ifp2->name;
68
paul90578522003-09-23 23:46:01 +000069 while (*p1 && *p2) {
paul106d2fd2003-08-01 00:24:13 +000070 /* look up to any number */
71 l1 = strcspn(p1, "0123456789");
72 l2 = strcspn(p2, "0123456789");
73
74 /* name lengths are different -> compare names */
75 if (l1 != l2)
76 return (strcmp(p1, p2));
77
paul3a0391a2004-07-17 11:51:29 +000078 /* Note that this relies on all numbers being less than all letters, so
79 * that de0 < del0.
80 */
paul106d2fd2003-08-01 00:24:13 +000081 res = strncmp(p1, p2, l1);
82
83 /* names are different -> compare them */
84 if (res)
85 return res;
86
87 /* with identical name part, go to numeric part */
paul106d2fd2003-08-01 00:24:13 +000088 p1 += l1;
89 p2 += l1;
90
paulb06c14f2004-07-09 12:24:42 +000091 if (!*p1)
92 return -1;
93 if (!*p2)
94 return 1;
95
paul106d2fd2003-08-01 00:24:13 +000096 x1 = strtol(p1, &p1, 10);
97 x2 = strtol(p2, &p2, 10);
98
99 /* let's compare numbers now */
100 if (x1 < x2)
101 return -1;
102 if (x1 > x2)
103 return 1;
104
105 /* numbers were equal, lets do it again..
106 (it happens with name like "eth123.456:789") */
107 }
paul90578522003-09-23 23:46:01 +0000108 if (*p1)
109 return 1;
110 if (*p2)
111 return -1;
112 return 0;
paul106d2fd2003-08-01 00:24:13 +0000113}
114
paul718e3742002-12-13 20:15:29 +0000115/* Create new interface structure. */
116struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200117if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000118{
119 struct interface *ifp;
Feng Lu5a5702f2015-05-22 11:39:59 +0200120 struct list *intf_list = vrf_iflist_get (vrf_id);
paul718e3742002-12-13 20:15:29 +0000121
ajsd2fc8892005-04-02 18:38:43 +0000122 ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
123 ifp->ifindex = IFINDEX_INTERNAL;
paul718e3742002-12-13 20:15:29 +0000124
paul106d2fd2003-08-01 00:24:13 +0000125 assert (name);
ajsd2fc8892005-04-02 18:38:43 +0000126 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */
paul106d2fd2003-08-01 00:24:13 +0000127 strncpy (ifp->name, name, namelen);
ajsd2fc8892005-04-02 18:38:43 +0000128 ifp->name[namelen] = '\0';
Feng Lu5a5702f2015-05-22 11:39:59 +0200129 ifp->vrf_id = vrf_id;
130 if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL)
131 listnode_add_sort (intf_list, ifp);
ajsd2fc8892005-04-02 18:38:43 +0000132 else
133 zlog_err("if_create(%s): corruption detected -- interface with this "
Feng Lu5a5702f2015-05-22 11:39:59 +0200134 "name exists already in VRF %u!", ifp->name, vrf_id);
paul718e3742002-12-13 20:15:29 +0000135 ifp->connected = list_new ();
136 ifp->connected->del = (void (*) (void *)) connected_free;
137
138 if (if_master.if_new_hook)
139 (*if_master.if_new_hook) (ifp);
140
141 return ifp;
142}
143
Feng Lu5a5702f2015-05-22 11:39:59 +0200144struct interface *
145if_create (const char *name, int namelen)
146{
147 return if_create_vrf (name, namelen, VRF_DEFAULT);
148}
149
ajsd2fc8892005-04-02 18:38:43 +0000150/* Delete interface structure. */
151void
152if_delete_retain (struct interface *ifp)
153{
154 if (if_master.if_delete_hook)
155 (*if_master.if_delete_hook) (ifp);
156
157 /* Free connected address list */
Josh Bailey2dd04c52012-03-21 10:37:03 -0700158 list_delete_all_node (ifp->connected);
ajsd2fc8892005-04-02 18:38:43 +0000159}
160
paul718e3742002-12-13 20:15:29 +0000161/* Delete and free interface structure. */
162void
163if_delete (struct interface *ifp)
164{
Feng Lu5a5702f2015-05-22 11:39:59 +0200165 listnode_delete (vrf_iflist (ifp->vrf_id), ifp);
paul718e3742002-12-13 20:15:29 +0000166
ajsd2fc8892005-04-02 18:38:43 +0000167 if_delete_retain(ifp);
paul718e3742002-12-13 20:15:29 +0000168
Josh Bailey2dd04c52012-03-21 10:37:03 -0700169 list_free (ifp->connected);
170
Olivier Dugeonae51c9d2016-04-19 16:21:46 +0200171 if_link_params_free (ifp);
172
paul718e3742002-12-13 20:15:29 +0000173 XFREE (MTYPE_IF, ifp);
174}
175
176/* Add hook to interface master. */
177void
178if_add_hook (int type, int (*func)(struct interface *ifp))
179{
180 switch (type) {
181 case IF_NEW_HOOK:
182 if_master.if_new_hook = func;
183 break;
184 case IF_DELETE_HOOK:
185 if_master.if_delete_hook = func;
186 break;
187 default:
188 break;
189 }
190}
191
192/* Interface existance check by index. */
193struct interface *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000194if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000195{
hasso52dc7ee2004-09-23 19:18:23 +0000196 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000197 struct interface *ifp;
198
Feng Lu5a5702f2015-05-22 11:39:59 +0200199 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000200 {
Paul Jakma9099f9b2016-01-18 10:12:10 +0000201 if (ifp->ifindex == ifindex)
paul718e3742002-12-13 20:15:29 +0000202 return ifp;
203 }
204 return NULL;
205}
206
Feng Lu5a5702f2015-05-22 11:39:59 +0200207struct interface *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000208if_lookup_by_index (ifindex_t ifindex)
Feng Lu5a5702f2015-05-22 11:39:59 +0200209{
Paul Jakma9099f9b2016-01-18 10:12:10 +0000210 return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT);
Feng Lu5a5702f2015-05-22 11:39:59 +0200211}
212
paul8cc41982005-05-06 21:25:49 +0000213const char *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000214ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000215{
paul718e3742002-12-13 20:15:29 +0000216 struct interface *ifp;
217
Paul Jakma9099f9b2016-01-18 10:12:10 +0000218 return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ?
paul8cc41982005-05-06 21:25:49 +0000219 ifp->name : "unknown";
ajsd2fc8892005-04-02 18:38:43 +0000220}
221
Feng Lu5a5702f2015-05-22 11:39:59 +0200222const char *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000223ifindex2ifname (ifindex_t ifindex)
Feng Lu5a5702f2015-05-22 11:39:59 +0200224{
Paul Jakma9099f9b2016-01-18 10:12:10 +0000225 return ifindex2ifname_vrf (ifindex, VRF_DEFAULT);
Feng Lu5a5702f2015-05-22 11:39:59 +0200226}
227
Paul Jakma9099f9b2016-01-18 10:12:10 +0000228ifindex_t
Feng Lu5a5702f2015-05-22 11:39:59 +0200229ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id)
230{
231 struct interface *ifp;
232
233 return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex
234 : IFINDEX_INTERNAL;
235}
236
Paul Jakma9099f9b2016-01-18 10:12:10 +0000237ifindex_t
ajsd2fc8892005-04-02 18:38:43 +0000238ifname2ifindex (const char *name)
239{
Feng Lu5a5702f2015-05-22 11:39:59 +0200240 return ifname2ifindex_vrf (name, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000241}
242
243/* Interface existance check by interface name. */
244struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200245if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000246{
hasso52dc7ee2004-09-23 19:18:23 +0000247 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000248 struct interface *ifp;
Paul Jakma3e4ee952009-08-06 12:08:50 +0100249
250 if (name)
Feng Lu5a5702f2015-05-22 11:39:59 +0200251 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
Paul Jakma3e4ee952009-08-06 12:08:50 +0100252 {
253 if (strcmp(name, ifp->name) == 0)
254 return ifp;
255 }
paul718e3742002-12-13 20:15:29 +0000256 return NULL;
257}
258
ajsa3491982005-04-02 22:50:38 +0000259struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200260if_lookup_by_name (const char *name)
261{
262 return if_lookup_by_name_vrf (name, VRF_DEFAULT);
263}
264
265struct interface *
266if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
ajsa3491982005-04-02 22:50:38 +0000267{
268 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000269 struct interface *ifp;
ajsa3491982005-04-02 22:50:38 +0000270
271 if (namelen > INTERFACE_NAMSIZ)
272 return NULL;
273
Feng Lu5a5702f2015-05-22 11:39:59 +0200274 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
ajsa3491982005-04-02 22:50:38 +0000275 {
ajsa3491982005-04-02 22:50:38 +0000276 if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0'))
277 return ifp;
278 }
279 return NULL;
280}
281
Feng Lu5a5702f2015-05-22 11:39:59 +0200282struct interface *
283if_lookup_by_name_len(const char *name, size_t namelen)
284{
285 return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT);
286}
287
paul718e3742002-12-13 20:15:29 +0000288/* Lookup interface by IPv4 address. */
289struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200290if_lookup_exact_address_vrf (struct in_addr src, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000291{
hasso52dc7ee2004-09-23 19:18:23 +0000292 struct listnode *node;
293 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000294 struct interface *ifp;
295 struct prefix *p;
296 struct connected *c;
297
Feng Lu5a5702f2015-05-22 11:39:59 +0200298 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000299 {
paul1eb8ef22005-04-07 07:30:20 +0000300 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
paul718e3742002-12-13 20:15:29 +0000301 {
paul718e3742002-12-13 20:15:29 +0000302 p = c->address;
303
304 if (p && p->family == AF_INET)
305 {
306 if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
307 return ifp;
308 }
309 }
310 }
311 return NULL;
312}
313
Feng Lu5a5702f2015-05-22 11:39:59 +0200314struct interface *
315if_lookup_exact_address (struct in_addr src)
316{
317 return if_lookup_exact_address_vrf (src, VRF_DEFAULT);
318}
319
paul718e3742002-12-13 20:15:29 +0000320/* Lookup interface by IPv4 address. */
321struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200322if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000323{
hasso52dc7ee2004-09-23 19:18:23 +0000324 struct listnode *node;
paul718e3742002-12-13 20:15:29 +0000325 struct prefix addr;
hasso3fb9cd62004-10-19 19:44:43 +0000326 int bestlen = 0;
hasso52dc7ee2004-09-23 19:18:23 +0000327 struct listnode *cnode;
paul718e3742002-12-13 20:15:29 +0000328 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +0000329 struct connected *c;
330 struct interface *match;
331
paul718e3742002-12-13 20:15:29 +0000332 addr.family = AF_INET;
333 addr.u.prefix4 = src;
334 addr.prefixlen = IPV4_MAX_BITLEN;
335
336 match = NULL;
337
Feng Lu5a5702f2015-05-22 11:39:59 +0200338 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000339 {
paul1eb8ef22005-04-07 07:30:20 +0000340 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
paul718e3742002-12-13 20:15:29 +0000341 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000342 if (c->address && (c->address->family == AF_INET) &&
343 prefix_match(CONNECTED_PREFIX(c), &addr) &&
344 (c->address->prefixlen > bestlen))
paul718e3742002-12-13 20:15:29 +0000345 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000346 bestlen = c->address->prefixlen;
347 match = ifp;
paul718e3742002-12-13 20:15:29 +0000348 }
349 }
350 }
351 return match;
352}
353
Feng Lu5a5702f2015-05-22 11:39:59 +0200354struct interface *
355if_lookup_address (struct in_addr src)
356{
357 return if_lookup_address_vrf (src, VRF_DEFAULT);
358}
359
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000360/* Lookup interface by prefix */
361struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200362if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id)
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000363{
364 struct listnode *node;
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000365 struct listnode *cnode;
366 struct interface *ifp;
367 struct connected *c;
368
Feng Lu5a5702f2015-05-22 11:39:59 +0200369 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
Dinesh Duttb81e97a2013-08-24 07:55:50 +0000370 {
371 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
372 {
373 if (prefix_cmp(c->address, prefix) == 0)
374 {
375 return ifp;
376 }
377 }
378 }
379 return NULL;
380}
381
Feng Lu5a5702f2015-05-22 11:39:59 +0200382struct interface *
383if_lookup_prefix (struct prefix *prefix)
384{
385 return if_lookup_prefix_vrf (prefix, VRF_DEFAULT);
386}
387
paul718e3742002-12-13 20:15:29 +0000388/* Get interface by name if given name interface doesn't exist create
389 one. */
390struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200391if_get_by_name_vrf (const char *name, vrf_id_t vrf_id)
paul718e3742002-12-13 20:15:29 +0000392{
393 struct interface *ifp;
394
Feng Lu5a5702f2015-05-22 11:39:59 +0200395 return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp :
396 if_create_vrf (name, strlen(name), vrf_id);
ajsa3491982005-04-02 22:50:38 +0000397}
398
399struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200400if_get_by_name (const char *name)
401{
402 return if_get_by_name_vrf (name, VRF_DEFAULT);
403}
404
405struct interface *
406if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id)
ajsa3491982005-04-02 22:50:38 +0000407{
408 struct interface *ifp;
409
Feng Lu5a5702f2015-05-22 11:39:59 +0200410 return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \
411 ifp : if_create_vrf (name, namelen, vrf_id);
412}
413
414struct interface *
415if_get_by_name_len (const char *name, size_t namelen)
416{
417 return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT);
paul718e3742002-12-13 20:15:29 +0000418}
419
420/* Does interface up ? */
421int
422if_is_up (struct interface *ifp)
423{
424 return ifp->flags & IFF_UP;
425}
426
paul2e3b2e42002-12-13 21:03:13 +0000427/* Is interface running? */
428int
429if_is_running (struct interface *ifp)
430{
431 return ifp->flags & IFF_RUNNING;
432}
433
434/* Is the interface operative, eg. either UP & RUNNING
435 or UP & !ZEBRA_INTERFACE_LINK_DETECTION */
436int
437if_is_operative (struct interface *ifp)
438{
439 return ((ifp->flags & IFF_UP) &&
440 (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
441}
442
paul718e3742002-12-13 20:15:29 +0000443/* Is this loopback interface ? */
444int
445if_is_loopback (struct interface *ifp)
446{
paul4ba9b922004-12-21 22:34:58 +0000447 /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M
448 * but Y on platform N?
449 */
450 return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL));
paul718e3742002-12-13 20:15:29 +0000451}
452
453/* Does this interface support broadcast ? */
454int
455if_is_broadcast (struct interface *ifp)
456{
457 return ifp->flags & IFF_BROADCAST;
458}
459
460/* Does this interface support broadcast ? */
461int
462if_is_pointopoint (struct interface *ifp)
463{
464 return ifp->flags & IFF_POINTOPOINT;
465}
466
467/* Does this interface support multicast ? */
468int
469if_is_multicast (struct interface *ifp)
470{
471 return ifp->flags & IFF_MULTICAST;
472}
473
474/* Printout flag information into log */
475const char *
476if_flag_dump (unsigned long flag)
477{
478 int separator = 0;
479 static char logbuf[BUFSIZ];
480
481#define IFF_OUT_LOG(X,STR) \
paul4ba9b922004-12-21 22:34:58 +0000482 if (flag & (X)) \
paul718e3742002-12-13 20:15:29 +0000483 { \
484 if (separator) \
485 strlcat (logbuf, ",", BUFSIZ); \
486 else \
487 separator = 1; \
488 strlcat (logbuf, STR, BUFSIZ); \
489 }
490
Paul Jakma630c97c2006-06-15 12:48:17 +0000491 strlcpy (logbuf, "<", BUFSIZ);
paul718e3742002-12-13 20:15:29 +0000492 IFF_OUT_LOG (IFF_UP, "UP");
493 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST");
494 IFF_OUT_LOG (IFF_DEBUG, "DEBUG");
495 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK");
496 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT");
497 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS");
498 IFF_OUT_LOG (IFF_RUNNING, "RUNNING");
499 IFF_OUT_LOG (IFF_NOARP, "NOARP");
500 IFF_OUT_LOG (IFF_PROMISC, "PROMISC");
501 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI");
502 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE");
503 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX");
504 IFF_OUT_LOG (IFF_LINK0, "LINK0");
505 IFF_OUT_LOG (IFF_LINK1, "LINK1");
506 IFF_OUT_LOG (IFF_LINK2, "LINK2");
507 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST");
paul4ba9b922004-12-21 22:34:58 +0000508 IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT");
509 IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH");
510 IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL");
511 IFF_OUT_LOG (IFF_IPV4, "IPv4");
512 IFF_OUT_LOG (IFF_IPV6, "IPv6");
paul718e3742002-12-13 20:15:29 +0000513
514 strlcat (logbuf, ">", BUFSIZ);
515
516 return logbuf;
Paul Jakma630c97c2006-06-15 12:48:17 +0000517#undef IFF_OUT_LOG
paul718e3742002-12-13 20:15:29 +0000518}
519
520/* For debugging */
paul8cc41982005-05-06 21:25:49 +0000521static void
Stephen Hemmingercedd7f22009-06-12 16:58:49 +0100522if_dump (const struct interface *ifp)
paul718e3742002-12-13 20:15:29 +0000523{
hasso52dc7ee2004-09-23 19:18:23 +0000524 struct listnode *node;
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100525 struct connected *c __attribute__((unused));
paul718e3742002-12-13 20:15:29 +0000526
paul1eb8ef22005-04-07 07:30:20 +0000527 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c))
Feng Lu2fc97f62015-05-22 11:39:57 +0200528 zlog_info ("Interface %s vrf %u index %d metric %d mtu %d "
paul4a7aac12004-05-08 05:00:31 +0000529#ifdef HAVE_IPV6
Paul Jakma23be94e2012-01-06 16:07:39 +0000530 "mtu6 %d "
paul4a7aac12004-05-08 05:00:31 +0000531#endif /* HAVE_IPV6 */
Paul Jakma23be94e2012-01-06 16:07:39 +0000532 "%s",
Feng Lu2fc97f62015-05-22 11:39:57 +0200533 ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu,
paul4a7aac12004-05-08 05:00:31 +0000534#ifdef HAVE_IPV6
Paul Jakma23be94e2012-01-06 16:07:39 +0000535 ifp->mtu6,
paul4a7aac12004-05-08 05:00:31 +0000536#endif /* HAVE_IPV6 */
Paul Jakma23be94e2012-01-06 16:07:39 +0000537 if_flag_dump (ifp->flags));
paul718e3742002-12-13 20:15:29 +0000538}
539
540/* Interface printing for all interface. */
541void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -0800542if_dump_all (void)
paul718e3742002-12-13 20:15:29 +0000543{
Feng Lu5a5702f2015-05-22 11:39:59 +0200544 struct list *intf_list;
hasso52dc7ee2004-09-23 19:18:23 +0000545 struct listnode *node;
paul1eb8ef22005-04-07 07:30:20 +0000546 void *p;
Feng Lu5a5702f2015-05-22 11:39:59 +0200547 vrf_iter_t iter;
paul718e3742002-12-13 20:15:29 +0000548
Feng Lu5a5702f2015-05-22 11:39:59 +0200549 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
550 if ((intf_list = vrf_iter2iflist (iter)) != NULL)
551 for (ALL_LIST_ELEMENTS_RO (intf_list, node, p))
552 if_dump (p);
paul718e3742002-12-13 20:15:29 +0000553}
554
555DEFUN (interface_desc,
556 interface_desc_cmd,
557 "description .LINE",
558 "Interface specific description\n"
559 "Characters describing this interface\n")
560{
paul718e3742002-12-13 20:15:29 +0000561 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +0000562
563 if (argc == 0)
564 return CMD_SUCCESS;
565
566 ifp = vty->index;
567 if (ifp->desc)
ajs3b8b1852005-01-29 18:19:13 +0000568 XFREE (MTYPE_TMP, ifp->desc);
569 ifp->desc = argv_concat(argv, argc, 0);
paul718e3742002-12-13 20:15:29 +0000570
571 return CMD_SUCCESS;
572}
573
574DEFUN (no_interface_desc,
575 no_interface_desc_cmd,
576 "no description",
577 NO_STR
578 "Interface specific description\n")
579{
580 struct interface *ifp;
581
582 ifp = vty->index;
583 if (ifp->desc)
paul02416842005-10-26 05:05:16 +0000584 XFREE (MTYPE_TMP, ifp->desc);
paul718e3742002-12-13 20:15:29 +0000585 ifp->desc = NULL;
586
587 return CMD_SUCCESS;
588}
David Lamparter6b0655a2014-06-04 06:53:35 +0200589
Paul Jakma98954842006-10-15 23:33:50 +0000590#ifdef SUNOS_5
591/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created
592 * a seperate struct interface for each logical interface, so config
593 * file may be full of 'interface fooX:Y'. Solaris however does not
594 * expose logical interfaces via PF_ROUTE, so trying to track logical
595 * interfaces can be fruitless, for that reason Quagga only tracks
596 * the primary IP interface.
597 *
598 * We try accomodate SUNWzebra by:
599 * - looking up the interface name, to see whether it exists, if so
600 * its useable
601 * - for protocol daemons, this could only because zebra told us of
602 * the interface
603 * - for zebra, only because it learnt from kernel
604 * - if not:
605 * - search the name to see if it contains a sub-ipif / logical interface
606 * seperator, the ':' char. If it does:
607 * - text up to that char must be the primary name - get that name.
608 * if not:
609 * - no idea, just get the name in its entirety.
610 */
611static struct interface *
Feng Lu5a5702f2015-05-22 11:39:59 +0200612if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id)
Paul Jakma98954842006-10-15 23:33:50 +0000613{
614 struct interface *ifp;
615 size_t seppos = 0;
paul718e3742002-12-13 20:15:29 +0000616
Feng Lu5a5702f2015-05-22 11:39:59 +0200617 if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL)
Paul Jakma98954842006-10-15 23:33:50 +0000618 return ifp;
619
620 /* hunt the primary interface name... */
621 while (seppos < nlen && name[seppos] != ':')
622 seppos++;
623
624 /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */
625 if (seppos < nlen)
Feng Lu5a5702f2015-05-22 11:39:59 +0200626 return if_get_by_name_len_vrf (name, seppos, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000627 else
Feng Lu5a5702f2015-05-22 11:39:59 +0200628 return if_get_by_name_len_vrf (name, nlen, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000629}
630#endif /* SUNOS_5 */
David Lamparter6b0655a2014-06-04 06:53:35 +0200631
paul718e3742002-12-13 20:15:29 +0000632DEFUN (interface,
633 interface_cmd,
634 "interface IFNAME",
635 "Select an interface to configure\n"
636 "Interface's name\n")
637{
638 struct interface *ifp;
ajsd2fc8892005-04-02 18:38:43 +0000639 size_t sl;
Feng Lu5a5702f2015-05-22 11:39:59 +0200640 vrf_id_t vrf_id = VRF_DEFAULT;
ajsd2fc8892005-04-02 18:38:43 +0000641
642 if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ)
643 {
644 vty_out (vty, "%% Interface name %s is invalid: length exceeds "
645 "%d characters%s",
646 argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE);
647 return CMD_WARNING;
648 }
paul718e3742002-12-13 20:15:29 +0000649
Feng Lu471ea392015-05-22 11:40:00 +0200650 if (argc > 1)
651 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
652
Paul Jakma98954842006-10-15 23:33:50 +0000653#ifdef SUNOS_5
Feng Lu5a5702f2015-05-22 11:39:59 +0200654 ifp = if_sunwzebra_get (argv[0], sl, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000655#else
Feng Lu5a5702f2015-05-22 11:39:59 +0200656 ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id);
Paul Jakma98954842006-10-15 23:33:50 +0000657#endif /* SUNOS_5 */
paul718e3742002-12-13 20:15:29 +0000658
paul718e3742002-12-13 20:15:29 +0000659 vty->index = ifp;
660 vty->node = INTERFACE_NODE;
661
662 return CMD_SUCCESS;
663}
664
Feng Lu471ea392015-05-22 11:40:00 +0200665ALIAS (interface,
666 interface_vrf_cmd,
667 "interface IFNAME " VRF_CMD_STR,
668 "Select an interface to configure\n"
669 "Interface's name\n"
670 VRF_CMD_HELP_STR)
671
paul32d24632003-05-23 09:25:20 +0000672DEFUN_NOSH (no_interface,
673 no_interface_cmd,
674 "no interface IFNAME",
675 NO_STR
676 "Delete a pseudo interface's configuration\n"
677 "Interface's name\n")
678{
679 // deleting interface
680 struct interface *ifp;
Feng Lu5a5702f2015-05-22 11:39:59 +0200681 vrf_id_t vrf_id = VRF_DEFAULT;
paul32d24632003-05-23 09:25:20 +0000682
Feng Lu471ea392015-05-22 11:40:00 +0200683 if (argc > 1)
684 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]);
685
Feng Lu5a5702f2015-05-22 11:39:59 +0200686 ifp = if_lookup_by_name_vrf (argv[0], vrf_id);
paul32d24632003-05-23 09:25:20 +0000687
688 if (ifp == NULL)
ajsd2fc8892005-04-02 18:38:43 +0000689 {
690 vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE);
691 return CMD_WARNING;
692 }
paul32d24632003-05-23 09:25:20 +0000693
paulbfc13532003-05-24 06:40:04 +0000694 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
ajsd2fc8892005-04-02 18:38:43 +0000695 {
696 vty_out (vty, "%% Only inactive interfaces can be deleted%s",
697 VTY_NEWLINE);
698 return CMD_WARNING;
699 }
paul32d24632003-05-23 09:25:20 +0000700
701 if_delete(ifp);
702
703 return CMD_SUCCESS;
704}
705
Feng Lu471ea392015-05-22 11:40:00 +0200706ALIAS (no_interface,
707 no_interface_vrf_cmd,
708 "no interface IFNAME " VRF_CMD_STR,
709 NO_STR
710 "Delete a pseudo interface's configuration\n"
711 "Interface's name\n"
712 VRF_CMD_HELP_STR)
713
paul718e3742002-12-13 20:15:29 +0000714/* For debug purpose. */
715DEFUN (show_address,
716 show_address_cmd,
717 "show address",
718 SHOW_STR
719 "address\n")
720{
hasso52dc7ee2004-09-23 19:18:23 +0000721 struct listnode *node;
722 struct listnode *node2;
paul718e3742002-12-13 20:15:29 +0000723 struct interface *ifp;
724 struct connected *ifc;
725 struct prefix *p;
Feng Lu5a5702f2015-05-22 11:39:59 +0200726 vrf_id_t vrf_id = VRF_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000727
Feng Lu5a5702f2015-05-22 11:39:59 +0200728 if (argc > 0)
729 VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]);
730
731 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp))
paul718e3742002-12-13 20:15:29 +0000732 {
paul1eb8ef22005-04-07 07:30:20 +0000733 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
paul718e3742002-12-13 20:15:29 +0000734 {
paul718e3742002-12-13 20:15:29 +0000735 p = ifc->address;
736
737 if (p->family == AF_INET)
738 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
739 VTY_NEWLINE);
740 }
741 }
742 return CMD_SUCCESS;
743}
744
Feng Lu5a5702f2015-05-22 11:39:59 +0200745ALIAS (show_address,
746 show_address_vrf_cmd,
747 "show address " VRF_CMD_STR,
748 SHOW_STR
749 "address\n"
750 VRF_CMD_HELP_STR)
751
752DEFUN (show_address_vrf_all,
753 show_address_vrf_all_cmd,
754 "show address " VRF_ALL_CMD_STR,
755 SHOW_STR
756 "address\n"
757 VRF_ALL_CMD_HELP_STR)
758{
759 struct list *intf_list;
760 struct listnode *node;
761 struct listnode *node2;
762 struct interface *ifp;
763 struct connected *ifc;
764 struct prefix *p;
765 vrf_iter_t iter;
766
767 for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
768 {
769 intf_list = vrf_iter2iflist (iter);
770 if (!intf_list || !listcount (intf_list))
771 continue;
772
773 vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter),
774 VTY_NEWLINE, VTY_NEWLINE);
775
776 for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp))
777 {
778 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc))
779 {
780 p = ifc->address;
781
782 if (p->family == AF_INET)
783 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen,
784 VTY_NEWLINE);
785 }
786 }
787 }
788 return CMD_SUCCESS;
789}
790
paul718e3742002-12-13 20:15:29 +0000791/* Allocate connected structure. */
792struct connected *
paul8cc41982005-05-06 21:25:49 +0000793connected_new (void)
paul718e3742002-12-13 20:15:29 +0000794{
Stephen Hemminger393deb92008-08-18 14:13:29 -0700795 return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected));
paul718e3742002-12-13 20:15:29 +0000796}
797
798/* Free connected structure. */
799void
800connected_free (struct connected *connected)
801{
802 if (connected->address)
803 prefix_free (connected->address);
804
805 if (connected->destination)
806 prefix_free (connected->destination);
807
808 if (connected->label)
paul9c4f1c62005-11-03 11:04:07 +0000809 XFREE (MTYPE_CONNECTED_LABEL, connected->label);
paul718e3742002-12-13 20:15:29 +0000810
811 XFREE (MTYPE_CONNECTED, connected);
812}
813
814/* Print if_addr structure. */
paul8cc41982005-05-06 21:25:49 +0000815static void __attribute__ ((unused))
paul718e3742002-12-13 20:15:29 +0000816connected_log (struct connected *connected, char *str)
817{
818 struct prefix *p;
819 struct interface *ifp;
820 char logbuf[BUFSIZ];
821 char buf[BUFSIZ];
822
823 ifp = connected->ifp;
824 p = connected->address;
825
Feng Lu2fc97f62015-05-22 11:39:57 +0200826 snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ",
827 str, ifp->name, ifp->vrf_id, prefix_family_str (p),
paul718e3742002-12-13 20:15:29 +0000828 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
829 p->prefixlen);
830
831 p = connected->destination;
832 if (p)
833 {
834 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
835 BUFSIZ - strlen(logbuf));
836 }
Christian Hammersfc951862011-03-23 13:07:55 +0300837 zlog (NULL, LOG_INFO, "%s", logbuf);
paul718e3742002-12-13 20:15:29 +0000838}
839
840/* If two connected address has same prefix return 1. */
paul8cc41982005-05-06 21:25:49 +0000841static int
paul718e3742002-12-13 20:15:29 +0000842connected_same_prefix (struct prefix *p1, struct prefix *p2)
843{
844 if (p1->family == p2->family)
845 {
846 if (p1->family == AF_INET &&
847 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4))
848 return 1;
849#ifdef HAVE_IPV6
850 if (p1->family == AF_INET6 &&
851 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6))
852 return 1;
853#endif /* HAVE_IPV6 */
854 }
855 return 0;
856}
857
858struct connected *
859connected_delete_by_prefix (struct interface *ifp, struct prefix *p)
860{
861 struct listnode *node;
862 struct listnode *next;
863 struct connected *ifc;
864
865 /* In case of same prefix come, replace it with new one. */
866 for (node = listhead (ifp->connected); node; node = next)
867 {
paul1eb8ef22005-04-07 07:30:20 +0000868 ifc = listgetdata (node);
paul718e3742002-12-13 20:15:29 +0000869 next = node->next;
870
871 if (connected_same_prefix (ifc->address, p))
872 {
873 listnode_delete (ifp->connected, ifc);
874 return ifc;
875 }
876 }
877 return NULL;
878}
879
paul727d1042002-12-13 20:50:29 +0000880/* Find the IPv4 address on our side that will be used when packets
881 are sent to dst. */
882struct connected *
883connected_lookup_address (struct interface *ifp, struct in_addr dst)
884{
885 struct prefix addr;
hasso52dc7ee2004-09-23 19:18:23 +0000886 struct listnode *cnode;
paul727d1042002-12-13 20:50:29 +0000887 struct connected *c;
888 struct connected *match;
889
paul727d1042002-12-13 20:50:29 +0000890 addr.family = AF_INET;
891 addr.u.prefix4 = dst;
892 addr.prefixlen = IPV4_MAX_BITLEN;
893
894 match = NULL;
895
paul1eb8ef22005-04-07 07:30:20 +0000896 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
paul727d1042002-12-13 20:50:29 +0000897 {
Andrew J. Schorre4529632006-12-12 19:18:21 +0000898 if (c->address && (c->address->family == AF_INET) &&
899 prefix_match(CONNECTED_PREFIX(c), &addr) &&
900 (!match || (c->address->prefixlen > match->address->prefixlen)))
901 match = c;
paul727d1042002-12-13 20:50:29 +0000902 }
903 return match;
904}
905
paul4a7aac12004-05-08 05:00:31 +0000906struct connected *
907connected_add_by_prefix (struct interface *ifp, struct prefix *p,
908 struct prefix *destination)
909{
910 struct connected *ifc;
911
912 /* Allocate new connected address. */
913 ifc = connected_new ();
914 ifc->ifp = ifp;
915
916 /* Fetch interface address */
917 ifc->address = prefix_new();
918 memcpy (ifc->address, p, sizeof(struct prefix));
919
920 /* Fetch dest address */
hasso3fb9cd62004-10-19 19:44:43 +0000921 if (destination)
922 {
923 ifc->destination = prefix_new();
924 memcpy (ifc->destination, destination, sizeof(struct prefix));
925 }
paul4a7aac12004-05-08 05:00:31 +0000926
927 /* Add connected address to the interface. */
928 listnode_add (ifp->connected, ifc);
929 return ifc;
930}
931
paul718e3742002-12-13 20:15:29 +0000932#ifndef HAVE_IF_NAMETOINDEX
Paul Jakma9099f9b2016-01-18 10:12:10 +0000933ifindex_t
paul718e3742002-12-13 20:15:29 +0000934if_nametoindex (const char *name)
935{
paul718e3742002-12-13 20:15:29 +0000936 struct interface *ifp;
937
ajs018546e2005-04-02 23:05:56 +0000938 return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL)
939 ? ifp->ifindex : 0;
paul718e3742002-12-13 20:15:29 +0000940}
941#endif
942
943#ifndef HAVE_IF_INDEXTONAME
944char *
Paul Jakma9099f9b2016-01-18 10:12:10 +0000945if_indextoname (ifindex_t ifindex, char *name)
paul718e3742002-12-13 20:15:29 +0000946{
paul718e3742002-12-13 20:15:29 +0000947 struct interface *ifp;
948
ajsd2fc8892005-04-02 18:38:43 +0000949 if (!(ifp = if_lookup_by_index(ifindex)))
950 return NULL;
951 strncpy (name, ifp->name, IFNAMSIZ);
952 return ifp->name;
paul718e3742002-12-13 20:15:29 +0000953}
954#endif
David Lamparter6b0655a2014-06-04 06:53:35 +0200955
paul8cc41982005-05-06 21:25:49 +0000956#if 0 /* this route_table of struct connected's is unused
957 * however, it would be good to use a route_table rather than
958 * a list..
959 */
paul718e3742002-12-13 20:15:29 +0000960/* Interface looking up by interface's address. */
paul718e3742002-12-13 20:15:29 +0000961/* Interface's IPv4 address reverse lookup table. */
962struct route_table *ifaddr_ipv4_table;
963/* struct route_table *ifaddr_ipv6_table; */
964
paul8cc41982005-05-06 21:25:49 +0000965static void
paul718e3742002-12-13 20:15:29 +0000966ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp)
967{
968 struct route_node *rn;
969 struct prefix_ipv4 p;
970
971 p.family = AF_INET;
972 p.prefixlen = IPV4_MAX_PREFIXLEN;
973 p.prefix = *ifaddr;
974
975 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p);
976 if (rn)
977 {
978 route_unlock_node (rn);
979 zlog_info ("ifaddr_ipv4_add(): address %s is already added",
980 inet_ntoa (*ifaddr));
981 return;
982 }
983 rn->info = ifp;
984}
985
paul8cc41982005-05-06 21:25:49 +0000986static void
paul718e3742002-12-13 20:15:29 +0000987ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp)
988{
989 struct route_node *rn;
990 struct prefix_ipv4 p;
991
992 p.family = AF_INET;
993 p.prefixlen = IPV4_MAX_PREFIXLEN;
994 p.prefix = *ifaddr;
995
996 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
997 if (! rn)
998 {
999 zlog_info ("ifaddr_ipv4_delete(): can't find address %s",
1000 inet_ntoa (*ifaddr));
1001 return;
1002 }
1003 rn->info = NULL;
1004 route_unlock_node (rn);
1005 route_unlock_node (rn);
1006}
1007
1008/* Lookup interface by interface's IP address or interface index. */
paul8cc41982005-05-06 21:25:49 +00001009static struct interface *
Paul Jakma9099f9b2016-01-18 10:12:10 +00001010ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
paul718e3742002-12-13 20:15:29 +00001011{
1012 struct prefix_ipv4 p;
1013 struct route_node *rn;
1014 struct interface *ifp;
paul718e3742002-12-13 20:15:29 +00001015
1016 if (addr)
1017 {
1018 p.family = AF_INET;
1019 p.prefixlen = IPV4_MAX_PREFIXLEN;
1020 p.prefix = *addr;
1021
1022 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
1023 if (! rn)
1024 return NULL;
1025
1026 ifp = rn->info;
1027 route_unlock_node (rn);
1028 return ifp;
1029 }
1030 else
ajsd2fc8892005-04-02 18:38:43 +00001031 return if_lookup_by_index(ifindex);
paul718e3742002-12-13 20:15:29 +00001032}
paul8cc41982005-05-06 21:25:49 +00001033#endif /* ifaddr_ipv4_table */
paul718e3742002-12-13 20:15:29 +00001034
1035/* Initialize interface list. */
1036void
Feng Lu5a5702f2015-05-22 11:39:59 +02001037if_init (vrf_id_t vrf_id, struct list **intf_list)
paul718e3742002-12-13 20:15:29 +00001038{
Feng Lu5a5702f2015-05-22 11:39:59 +02001039 *intf_list = list_new ();
paul8cc41982005-05-06 21:25:49 +00001040#if 0
paul718e3742002-12-13 20:15:29 +00001041 ifaddr_ipv4_table = route_table_init ();
paul8cc41982005-05-06 21:25:49 +00001042#endif /* ifaddr_ipv4_table */
paul718e3742002-12-13 20:15:29 +00001043
Feng Lu5a5702f2015-05-22 11:39:59 +02001044 (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
paul718e3742002-12-13 20:15:29 +00001045
Feng Lu5a5702f2015-05-22 11:39:59 +02001046 if (vrf_id == VRF_DEFAULT)
1047 iflist = *intf_list;
paul718e3742002-12-13 20:15:29 +00001048}
Tom Goff4bd045d2010-11-10 13:00:54 -08001049
1050void
Feng Lu5a5702f2015-05-22 11:39:59 +02001051if_terminate (vrf_id_t vrf_id, struct list **intf_list)
Tom Goff4bd045d2010-11-10 13:00:54 -08001052{
1053 for (;;)
1054 {
1055 struct interface *ifp;
1056
Feng Lu5a5702f2015-05-22 11:39:59 +02001057 ifp = listnode_head (*intf_list);
Tom Goff4bd045d2010-11-10 13:00:54 -08001058 if (ifp == NULL)
1059 break;
1060
1061 if_delete (ifp);
1062 }
1063
Feng Lu5a5702f2015-05-22 11:39:59 +02001064 list_delete (*intf_list);
1065 *intf_list = NULL;
1066
1067 if (vrf_id == VRF_DEFAULT)
1068 iflist = NULL;
Tom Goff4bd045d2010-11-10 13:00:54 -08001069}
Timo Teräs954c7d62016-01-15 17:36:33 +02001070
1071const char *
1072if_link_type_str (enum zebra_link_type llt)
1073{
1074 switch (llt)
1075 {
1076#define llts(T,S) case (T): return (S)
1077 llts(ZEBRA_LLT_UNKNOWN, "Unknown");
1078 llts(ZEBRA_LLT_ETHER, "Ethernet");
1079 llts(ZEBRA_LLT_EETHER, "Experimental Ethernet");
1080 llts(ZEBRA_LLT_AX25, "AX.25 Level 2");
1081 llts(ZEBRA_LLT_PRONET, "PROnet token ring");
1082 llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB");
1083 llts(ZEBRA_LLT_ARCNET, "ARCnet");
1084 llts(ZEBRA_LLT_APPLETLK, "AppleTalk");
1085 llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI");
1086 llts(ZEBRA_LLT_ATM, "ATM");
1087 llts(ZEBRA_LLT_METRICOM, "Metricom STRIP");
1088 llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4");
1089 llts(ZEBRA_LLT_EUI64, "EUI-64");
1090 llts(ZEBRA_LLT_INFINIBAND, "InfiniBand");
1091 llts(ZEBRA_LLT_SLIP, "SLIP");
1092 llts(ZEBRA_LLT_CSLIP, "Compressed SLIP");
1093 llts(ZEBRA_LLT_SLIP6, "SLIPv6");
1094 llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6");
1095 llts(ZEBRA_LLT_ROSE, "ROSE packet radio");
1096 llts(ZEBRA_LLT_X25, "CCITT X.25");
1097 llts(ZEBRA_LLT_PPP, "PPP");
1098 llts(ZEBRA_LLT_CHDLC, "Cisco HDLC");
1099 llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC");
1100 llts(ZEBRA_LLT_LAPB, "LAPB");
1101 llts(ZEBRA_LLT_IPIP, "IPIP Tunnel");
1102 llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel");
1103 llts(ZEBRA_LLT_FRAD, "FRAD");
1104 llts(ZEBRA_LLT_SKIP, "SKIP vif");
1105 llts(ZEBRA_LLT_LOOPBACK, "Loopback");
1106 llts(ZEBRA_LLT_LOCALTLK, "Localtalk");
1107 llts(ZEBRA_LLT_FDDI, "FDDI");
1108 llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT");
1109 llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel");
1110 llts(ZEBRA_LLT_IPGRE, "GRE over IP");
1111 llts(ZEBRA_LLT_PIMREG, "PIMSM registration");
1112 llts(ZEBRA_LLT_HIPPI, "HiPPI");
1113 llts(ZEBRA_LLT_IRDA, "IrDA");
1114 llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP");
1115 llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop");
1116 llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop");
1117 llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric");
1118 llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring");
1119 llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11");
1120 llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap");
1121 llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4");
1122 llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy");
1123 default:
1124 zlog_warn ("Unknown value %d", llt);
1125 return "Unknown type!";
1126#undef llts
1127 }
1128 return NULL;
1129}
Olivier Dugeonae51c9d2016-04-19 16:21:46 +02001130
1131struct if_link_params *
1132if_link_params_get (struct interface *ifp)
1133{
1134 if (ifp->link_params != NULL)
1135 return ifp->link_params;
1136
1137 struct if_link_params *iflp = XCALLOC(MTYPE_IF_LINK_PARAMS,
1138 sizeof (struct if_link_params));
1139 if (iflp == NULL) return NULL;
1140
1141 /* Set TE metric == standard metric */
1142 iflp->te_metric = ifp->metric;
1143
1144 /* Compute default bandwidth based on interface */
1145 int bw = (float)((ifp->bandwidth ? ifp->bandwidth : DEFAULT_BANDWIDTH)
1146 * TE_KILO_BIT / TE_BYTE);
1147
1148 /* Set Max, Reservable and Unreserved Bandwidth */
1149 iflp->max_bw = bw;
1150 iflp->max_rsv_bw = bw;
1151 for (int i = 0; i < MAX_CLASS_TYPE; i++)
1152 iflp->unrsv_bw[i] = bw;
1153
1154 /* Update Link parameters status */
1155 iflp->lp_status = LP_TE | LP_MAX_BW | LP_MAX_RSV_BW | LP_UNRSV_BW;
1156
1157 /* Finally attach newly created Link Parameters */
1158 ifp->link_params = iflp;
1159
1160 return iflp;
1161}
1162
1163void
1164if_link_params_free (struct interface *ifp)
1165{
1166 if (ifp->link_params == NULL) return;
1167 XFREE(MTYPE_IF_LINK_PARAMS, ifp->link_params);
1168 ifp->link_params = NULL;
1169}