--- embedaddon/quagga/lib/if.c 2012/02/21 17:26:12 1.1 +++ embedaddon/quagga/lib/if.c 2016/11/02 10:09:11 1.1.1.3 @@ -27,6 +27,7 @@ #include "vector.h" #include "vty.h" #include "command.h" +#include "vrf.h" #include "if.h" #include "sockunion.h" #include "prefix.h" @@ -35,8 +36,8 @@ #include "buffer.h" #include "str.h" #include "log.h" - -/* Master list of interfaces. */ + +/* List of interfaces in only the default VRF */ struct list *iflist; /* One for each program. This structure is needed to store hooks. */ @@ -44,8 +45,8 @@ struct if_master { int (*if_new_hook) (struct interface *); int (*if_delete_hook) (struct interface *); -} if_master; - +} if_master = {0,}; + /* Compare interface names, returning an integer greater than, equal to, or * less than 0, (following the strcmp convention), according to the * relationship between ifp1 and ifp2. Interface names consist of an @@ -113,9 +114,10 @@ if_cmp_func (struct interface *ifp1, struct interface /* Create new interface structure. */ struct interface * -if_create (const char *name, int namelen) +if_create_vrf (const char *name, int namelen, vrf_id_t vrf_id) { struct interface *ifp; + struct list *intf_list = vrf_iflist_get (vrf_id); ifp = XCALLOC (MTYPE_IF, sizeof (struct interface)); ifp->ifindex = IFINDEX_INTERNAL; @@ -124,11 +126,12 @@ if_create (const char *name, int namelen) assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ strncpy (ifp->name, name, namelen); ifp->name[namelen] = '\0'; - if (if_lookup_by_name(ifp->name) == NULL) - listnode_add_sort (iflist, ifp); + ifp->vrf_id = vrf_id; + if (if_lookup_by_name_vrf (ifp->name, vrf_id) == NULL) + listnode_add_sort (intf_list, ifp); else zlog_err("if_create(%s): corruption detected -- interface with this " - "name exists already!", ifp->name); + "name exists already in VRF %u!", ifp->name, vrf_id); ifp->connected = list_new (); ifp->connected->del = (void (*) (void *)) connected_free; @@ -138,6 +141,12 @@ if_create (const char *name, int namelen) return ifp; } +struct interface * +if_create (const char *name, int namelen) +{ + return if_create_vrf (name, namelen, VRF_DEFAULT); +} + /* Delete interface structure. */ void if_delete_retain (struct interface *ifp) @@ -146,17 +155,19 @@ if_delete_retain (struct interface *ifp) (*if_master.if_delete_hook) (ifp); /* Free connected address list */ - list_delete (ifp->connected); + list_delete_all_node (ifp->connected); } /* Delete and free interface structure. */ void if_delete (struct interface *ifp) { - listnode_delete (iflist, ifp); + listnode_delete (vrf_iflist (ifp->vrf_id), ifp); if_delete_retain(ifp); + list_free (ifp->connected); + XFREE (MTYPE_IF, ifp); } @@ -178,46 +189,64 @@ if_add_hook (int type, int (*func)(struct interface *i /* Interface existance check by index. */ struct interface * -if_lookup_by_index (unsigned int index) +if_lookup_by_index_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; - for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { - if (ifp->ifindex == index) + if (ifp->ifindex == ifindex) return ifp; } return NULL; } +struct interface * +if_lookup_by_index (ifindex_t ifindex) +{ + return if_lookup_by_index_vrf (ifindex, VRF_DEFAULT); +} + const char * -ifindex2ifname (unsigned int index) +ifindex2ifname_vrf (ifindex_t ifindex, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_index(index)) != NULL) ? + return ((ifp = if_lookup_by_index_vrf (ifindex, vrf_id)) != NULL) ? ifp->name : "unknown"; } -unsigned int -ifname2ifindex (const char *name) +const char * +ifindex2ifname (ifindex_t ifindex) { + return ifindex2ifname_vrf (ifindex, VRF_DEFAULT); +} + +ifindex_t +ifname2ifindex_vrf (const char *name, vrf_id_t vrf_id) +{ struct interface *ifp; - return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex + return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp->ifindex : IFINDEX_INTERNAL; } +ifindex_t +ifname2ifindex (const char *name) +{ + return ifname2ifindex_vrf (name, VRF_DEFAULT); +} + /* Interface existance check by interface name. */ struct interface * -if_lookup_by_name (const char *name) +if_lookup_by_name_vrf (const char *name, vrf_id_t vrf_id) { struct listnode *node; struct interface *ifp; if (name) - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { if (strcmp(name, ifp->name) == 0) return ifp; @@ -226,15 +255,21 @@ if_lookup_by_name (const char *name) } struct interface * -if_lookup_by_name_len(const char *name, size_t namelen) +if_lookup_by_name (const char *name) { + return if_lookup_by_name_vrf (name, VRF_DEFAULT); +} + +struct interface * +if_lookup_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id) +{ struct listnode *node; struct interface *ifp; if (namelen > INTERFACE_NAMSIZ) return NULL; - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0')) return ifp; @@ -242,9 +277,15 @@ if_lookup_by_name_len(const char *name, size_t namelen return NULL; } +struct interface * +if_lookup_by_name_len(const char *name, size_t namelen) +{ + return if_lookup_by_name_len_vrf (name, namelen, VRF_DEFAULT); +} + /* Lookup interface by IPv4 address. */ struct interface * -if_lookup_exact_address (struct in_addr src) +if_lookup_exact_address_vrf (struct in_addr src, vrf_id_t vrf_id) { struct listnode *node; struct listnode *cnode; @@ -252,7 +293,7 @@ if_lookup_exact_address (struct in_addr src) struct prefix *p; struct connected *c; - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) { @@ -268,9 +309,15 @@ if_lookup_exact_address (struct in_addr src) return NULL; } +struct interface * +if_lookup_exact_address (struct in_addr src) +{ + return if_lookup_exact_address_vrf (src, VRF_DEFAULT); +} + /* Lookup interface by IPv4 address. */ struct interface * -if_lookup_address (struct in_addr src) +if_lookup_address_vrf (struct in_addr src, vrf_id_t vrf_id) { struct listnode *node; struct prefix addr; @@ -286,7 +333,7 @@ if_lookup_address (struct in_addr src) match = NULL; - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) { @@ -302,26 +349,72 @@ if_lookup_address (struct in_addr src) return match; } +struct interface * +if_lookup_address (struct in_addr src) +{ + return if_lookup_address_vrf (src, VRF_DEFAULT); +} + +/* Lookup interface by prefix */ +struct interface * +if_lookup_prefix_vrf (struct prefix *prefix, vrf_id_t vrf_id) +{ + struct listnode *node; + struct listnode *cnode; + struct interface *ifp; + struct connected *c; + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) + { + for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) + { + if (prefix_cmp(c->address, prefix) == 0) + { + return ifp; + } + } + } + return NULL; +} + +struct interface * +if_lookup_prefix (struct prefix *prefix) +{ + return if_lookup_prefix_vrf (prefix, VRF_DEFAULT); +} + /* Get interface by name if given name interface doesn't exist create one. */ struct interface * -if_get_by_name (const char *name) +if_get_by_name_vrf (const char *name, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp : - if_create(name, strlen(name)); + return ((ifp = if_lookup_by_name_vrf (name, vrf_id)) != NULL) ? ifp : + if_create_vrf (name, strlen(name), vrf_id); } struct interface * -if_get_by_name_len(const char *name, size_t namelen) +if_get_by_name (const char *name) { + return if_get_by_name_vrf (name, VRF_DEFAULT); +} + +struct interface * +if_get_by_name_len_vrf (const char *name, size_t namelen, vrf_id_t vrf_id) +{ struct interface *ifp; - return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp : - if_create(name, namelen); + return ((ifp = if_lookup_by_name_len_vrf (name, namelen, vrf_id)) != NULL) ? \ + ifp : if_create_vrf (name, namelen, vrf_id); } +struct interface * +if_get_by_name_len (const char *name, size_t namelen) +{ + return if_get_by_name_len_vrf (name, namelen, VRF_DEFAULT); +} + /* Does interface up ? */ int if_is_up (struct interface *ifp) @@ -427,32 +520,34 @@ static void if_dump (const struct interface *ifp) { struct listnode *node; - struct connected *c; + struct connected *c __attribute__((unused)); - zlog_info ("Interface %s index %d metric %d mtu %d " + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c)) + zlog_info ("Interface %s vrf %u index %d metric %d mtu %d " #ifdef HAVE_IPV6 - "mtu6 %d " + "mtu6 %d " #endif /* HAVE_IPV6 */ - "%s", - ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, + "%s", + ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, #ifdef HAVE_IPV6 - ifp->mtu6, + ifp->mtu6, #endif /* HAVE_IPV6 */ - if_flag_dump (ifp->flags)); - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c)) - ; + if_flag_dump (ifp->flags)); } /* Interface printing for all interface. */ void if_dump_all (void) { + struct list *intf_list; struct listnode *node; void *p; + vrf_iter_t iter; - for (ALL_LIST_ELEMENTS_RO (iflist, node, p)) - if_dump (p); + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + if ((intf_list = vrf_iter2iflist (iter)) != NULL) + for (ALL_LIST_ELEMENTS_RO (intf_list, node, p)) + if_dump (p); } DEFUN (interface_desc, @@ -489,7 +584,7 @@ DEFUN (no_interface_desc, return CMD_SUCCESS; } - + #ifdef SUNOS_5 /* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created * a seperate struct interface for each logical interface, so config @@ -512,12 +607,12 @@ DEFUN (no_interface_desc, * - no idea, just get the name in its entirety. */ static struct interface * -if_sunwzebra_get (const char *name, size_t nlen) +if_sunwzebra_get (const char *name, size_t nlen, vrf_id_t vrf_id) { struct interface *ifp; size_t seppos = 0; - if ( (ifp = if_lookup_by_name_len(name, nlen)) != NULL) + if ( (ifp = if_lookup_by_name_len_vrf (name, nlen, vrf_id)) != NULL) return ifp; /* hunt the primary interface name... */ @@ -526,12 +621,12 @@ if_sunwzebra_get (const char *name, size_t nlen) /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ if (seppos < nlen) - return if_get_by_name_len (name, seppos); + return if_get_by_name_len_vrf (name, seppos, vrf_id); else - return if_get_by_name_len (name, nlen); + return if_get_by_name_len_vrf (name, nlen, vrf_id); } #endif /* SUNOS_5 */ - + DEFUN (interface, interface_cmd, "interface IFNAME", @@ -540,6 +635,7 @@ DEFUN (interface, { struct interface *ifp; size_t sl; + vrf_id_t vrf_id = VRF_DEFAULT; if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ) { @@ -549,10 +645,13 @@ DEFUN (interface, return CMD_WARNING; } + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + #ifdef SUNOS_5 - ifp = if_sunwzebra_get (argv[0], sl); + ifp = if_sunwzebra_get (argv[0], sl, vrf_id); #else - ifp = if_get_by_name_len(argv[0], sl); + ifp = if_get_by_name_len_vrf (argv[0], sl, vrf_id); #endif /* SUNOS_5 */ vty->index = ifp; @@ -561,6 +660,13 @@ DEFUN (interface, return CMD_SUCCESS; } +ALIAS (interface, + interface_vrf_cmd, + "interface IFNAME " VRF_CMD_STR, + "Select an interface to configure\n" + "Interface's name\n" + VRF_CMD_HELP_STR) + DEFUN_NOSH (no_interface, no_interface_cmd, "no interface IFNAME", @@ -570,9 +676,13 @@ DEFUN_NOSH (no_interface, { // deleting interface struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; - ifp = if_lookup_by_name (argv[0]); + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); + ifp = if_lookup_by_name_vrf (argv[0], vrf_id); + if (ifp == NULL) { vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE); @@ -591,6 +701,14 @@ DEFUN_NOSH (no_interface, return CMD_SUCCESS; } +ALIAS (no_interface, + no_interface_vrf_cmd, + "no interface IFNAME " VRF_CMD_STR, + NO_STR + "Delete a pseudo interface's configuration\n" + "Interface's name\n" + VRF_CMD_HELP_STR) + /* For debug purpose. */ DEFUN (show_address, show_address_cmd, @@ -603,8 +721,12 @@ DEFUN (show_address, struct interface *ifp; struct connected *ifc; struct prefix *p; + vrf_id_t vrf_id = VRF_DEFAULT; - for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) + if (argc > 0) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[0]); + + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) { @@ -618,6 +740,52 @@ DEFUN (show_address, return CMD_SUCCESS; } +ALIAS (show_address, + show_address_vrf_cmd, + "show address " VRF_CMD_STR, + SHOW_STR + "address\n" + VRF_CMD_HELP_STR) + +DEFUN (show_address_vrf_all, + show_address_vrf_all_cmd, + "show address " VRF_ALL_CMD_STR, + SHOW_STR + "address\n" + VRF_ALL_CMD_HELP_STR) +{ + struct list *intf_list; + struct listnode *node; + struct listnode *node2; + struct interface *ifp; + struct connected *ifc; + struct prefix *p; + vrf_iter_t iter; + + for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + { + intf_list = vrf_iter2iflist (iter); + if (!intf_list || !listcount (intf_list)) + continue; + + vty_out (vty, "%sVRF %u%s%s", VTY_NEWLINE, vrf_iter2id (iter), + VTY_NEWLINE, VTY_NEWLINE); + + for (ALL_LIST_ELEMENTS_RO (intf_list, node, ifp)) + { + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) + { + p = ifc->address; + + if (p->family == AF_INET) + vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen, + VTY_NEWLINE); + } + } + } + return CMD_SUCCESS; +} + /* Allocate connected structure. */ struct connected * connected_new (void) @@ -653,8 +821,8 @@ connected_log (struct connected *connected, char *str) ifp = connected->ifp; p = connected->address; - snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ", - str, ifp->name, prefix_family_str (p), + snprintf (logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", + str, ifp->name, ifp->vrf_id, prefix_family_str (p), inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); @@ -760,7 +928,7 @@ connected_add_by_prefix (struct interface *ifp, struct } #ifndef HAVE_IF_NAMETOINDEX -unsigned int +ifindex_t if_nametoindex (const char *name) { struct interface *ifp; @@ -772,7 +940,7 @@ if_nametoindex (const char *name) #ifndef HAVE_IF_INDEXTONAME char * -if_indextoname (unsigned int ifindex, char *name) +if_indextoname (ifindex_t ifindex, char *name) { struct interface *ifp; @@ -782,7 +950,7 @@ if_indextoname (unsigned int ifindex, char *name) return ifp->name; } #endif - + #if 0 /* this route_table of struct connected's is unused * however, it would be good to use a route_table rather than * a list.. @@ -837,7 +1005,7 @@ ifaddr_ipv4_delete (struct in_addr *ifaddr, struct int /* Lookup interface by interface's IP address or interface index. */ static struct interface * -ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex) +ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex) { struct prefix_ipv4 p; struct route_node *rn; @@ -864,35 +1032,96 @@ ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int /* Initialize interface list. */ void -if_init (void) +if_init (vrf_id_t vrf_id, struct list **intf_list) { - iflist = list_new (); + *intf_list = list_new (); #if 0 ifaddr_ipv4_table = route_table_init (); #endif /* ifaddr_ipv4_table */ - if (iflist) { - iflist->cmp = (int (*)(void *, void *))if_cmp_func; - return; - } + (*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func; - memset (&if_master, 0, sizeof if_master); + if (vrf_id == VRF_DEFAULT) + iflist = *intf_list; } void -if_terminate (void) +if_terminate (vrf_id_t vrf_id, struct list **intf_list) { for (;;) { struct interface *ifp; - ifp = listnode_head (iflist); + ifp = listnode_head (*intf_list); if (ifp == NULL) break; if_delete (ifp); } - list_delete (iflist); - iflist = NULL; + list_delete (*intf_list); + *intf_list = NULL; + + if (vrf_id == VRF_DEFAULT) + iflist = NULL; +} + +const char * +if_link_type_str (enum zebra_link_type llt) +{ + switch (llt) + { +#define llts(T,S) case (T): return (S) + llts(ZEBRA_LLT_UNKNOWN, "Unknown"); + llts(ZEBRA_LLT_ETHER, "Ethernet"); + llts(ZEBRA_LLT_EETHER, "Experimental Ethernet"); + llts(ZEBRA_LLT_AX25, "AX.25 Level 2"); + llts(ZEBRA_LLT_PRONET, "PROnet token ring"); + llts(ZEBRA_LLT_IEEE802, "IEEE 802.2 Ethernet/TR/TB"); + llts(ZEBRA_LLT_ARCNET, "ARCnet"); + llts(ZEBRA_LLT_APPLETLK, "AppleTalk"); + llts(ZEBRA_LLT_DLCI, "Frame Relay DLCI"); + llts(ZEBRA_LLT_ATM, "ATM"); + llts(ZEBRA_LLT_METRICOM, "Metricom STRIP"); + llts(ZEBRA_LLT_IEEE1394, "IEEE 1394 IPv4"); + llts(ZEBRA_LLT_EUI64, "EUI-64"); + llts(ZEBRA_LLT_INFINIBAND, "InfiniBand"); + llts(ZEBRA_LLT_SLIP, "SLIP"); + llts(ZEBRA_LLT_CSLIP, "Compressed SLIP"); + llts(ZEBRA_LLT_SLIP6, "SLIPv6"); + llts(ZEBRA_LLT_CSLIP6, "Compressed SLIPv6"); + llts(ZEBRA_LLT_ROSE, "ROSE packet radio"); + llts(ZEBRA_LLT_X25, "CCITT X.25"); + llts(ZEBRA_LLT_PPP, "PPP"); + llts(ZEBRA_LLT_CHDLC, "Cisco HDLC"); + llts(ZEBRA_LLT_RAWHDLC, "Raw HDLC"); + llts(ZEBRA_LLT_LAPB, "LAPB"); + llts(ZEBRA_LLT_IPIP, "IPIP Tunnel"); + llts(ZEBRA_LLT_IPIP6, "IPIP6 Tunnel"); + llts(ZEBRA_LLT_FRAD, "FRAD"); + llts(ZEBRA_LLT_SKIP, "SKIP vif"); + llts(ZEBRA_LLT_LOOPBACK, "Loopback"); + llts(ZEBRA_LLT_LOCALTLK, "Localtalk"); + llts(ZEBRA_LLT_FDDI, "FDDI"); + llts(ZEBRA_LLT_SIT, "IPv6-in-IPv4 SIT"); + llts(ZEBRA_LLT_IPDDP, "IP-in-DDP tunnel"); + llts(ZEBRA_LLT_IPGRE, "GRE over IP"); + llts(ZEBRA_LLT_PIMREG, "PIMSM registration"); + llts(ZEBRA_LLT_HIPPI, "HiPPI"); + llts(ZEBRA_LLT_IRDA, "IrDA"); + llts(ZEBRA_LLT_FCPP, "Fibre-Channel PtP"); + llts(ZEBRA_LLT_FCAL, "Fibre-Channel Arbitrated Loop"); + llts(ZEBRA_LLT_FCPL, "Fibre-Channel Public Loop"); + llts(ZEBRA_LLT_FCFABRIC, "Fibre-Channel Fabric"); + llts(ZEBRA_LLT_IEEE802_TR, "IEEE 802.2 Token Ring"); + llts(ZEBRA_LLT_IEEE80211, "IEEE 802.11"); + llts(ZEBRA_LLT_IEEE80211_RADIOTAP, "IEEE 802.11 Radiotap"); + llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); + llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); + default: + zlog_warn ("Unknown value %d", llt); + return "Unknown type!"; +#undef llts + } + return NULL; }