diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.am | 4 | ||||
| -rw-r--r-- | lib/if.c | 255 | ||||
| -rw-r--r-- | lib/if.h | 37 | ||||
| -rw-r--r-- | lib/memory.c | 43 | ||||
| -rw-r--r-- | lib/memtypes.c | 6 | ||||
| -rw-r--r-- | lib/prefix.c | 7 | ||||
| -rw-r--r-- | lib/prefix.h | 2 | ||||
| -rw-r--r-- | lib/routemap.c | 89 | ||||
| -rw-r--r-- | lib/vrf.c | 401 | ||||
| -rw-r--r-- | lib/vrf.h | 127 | ||||
| -rw-r--r-- | lib/zebra.h | 3 |
11 files changed, 864 insertions, 110 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index 19ae8f96df..49a721f7f9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -14,7 +14,7 @@ libzebra_la_SOURCES = \ filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \ - ptm_lib.c csv.c bfd.c + ptm_lib.c csv.c bfd.c vrf.c BUILT_SOURCES = memtypes.h route_types.h gitversion.h @@ -30,7 +30,7 @@ pkginclude_HEADERS = \ plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ workqueue.h route_types.h libospf.h nexthop.h json.h \ - ptm_lib.h csv.h bfd.h + ptm_lib.h csv.h bfd.h vrf.h EXTRA_DIST = \ regex.c regex-gnu.h \ @@ -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" @@ -36,7 +37,7 @@ #include "str.h" #include "log.h" -/* Master list of interfaces. */ +/* List of interfaces in only the default VRF */ struct list *iflist; int ptm_enable = 0; @@ -45,7 +46,7 @@ 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 @@ -114,9 +115,10 @@ if_cmp_func (struct interface *ifp1, struct interface *ifp2) /* 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; @@ -125,11 +127,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; @@ -145,6 +148,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) @@ -163,7 +172,7 @@ if_delete_retain (struct interface *ifp) void if_delete (struct interface *ifp) { - listnode_delete (iflist, ifp); + listnode_delete (vrf_iflist (ifp->vrf_id), ifp); if_delete_retain(ifp); @@ -191,12 +200,12 @@ if_add_hook (int type, int (*func)(struct interface *ifp)) /* Interface existance check by index. */ struct interface * -if_lookup_by_index (unsigned int index) +if_lookup_by_index_vrf (unsigned int index, 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) return ifp; @@ -204,33 +213,51 @@ if_lookup_by_index (unsigned int index) return NULL; } +struct interface * +if_lookup_by_index (unsigned int index) +{ + return if_lookup_by_index_vrf (index, VRF_DEFAULT); +} + const char * -ifindex2ifname (unsigned int index) +ifindex2ifname_vrf (unsigned int index, vrf_id_t vrf_id) { struct interface *ifp; - return ((ifp = if_lookup_by_index(index)) != NULL) ? + return ((ifp = if_lookup_by_index_vrf (index, vrf_id)) != NULL) ? ifp->name : "unknown"; } +const char * +ifindex2ifname (unsigned int index) +{ + return ifindex2ifname_vrf (index, VRF_DEFAULT); +} + unsigned int -ifname2ifindex (const char *name) +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; } +unsigned int +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; @@ -239,7 +266,13 @@ 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; @@ -247,7 +280,7 @@ if_lookup_by_name_len(const char *name, size_t namelen) 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; @@ -255,9 +288,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 (void *src, int family) +if_lookup_exact_address_vrf (void *src, int family, vrf_id_t vrf_id) { struct listnode *node; struct listnode *cnode; @@ -265,7 +304,7 @@ if_lookup_exact_address (void *src, int family) 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)) { @@ -289,9 +328,15 @@ if_lookup_exact_address (void *src, int family) return NULL; } +struct interface * +if_lookup_exact_address (void *src, int family) +{ + return if_lookup_exact_address_vrf (src, family, VRF_DEFAULT); +} + /* Lookup interface by IPv4 address. */ struct interface * -if_lookup_address (void *matchaddr, int family) +if_lookup_address_vrf (void *matchaddr, int family, vrf_id_t vrf_id) { struct listnode *node; struct prefix addr; @@ -316,7 +361,7 @@ if_lookup_address (void *matchaddr, int family) 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)) { @@ -332,6 +377,12 @@ if_lookup_address (void *matchaddr, int family) return match; } +struct interface * +if_lookup_address (void *matchaddr, int family) +{ + return if_lookup_address_vrf (matchaddr, family, VRF_DEFAULT); +} + /* Lookup anchor interface by IPv4 address. */ struct connected * if_anchor_lookup_by_address (struct in_addr src) @@ -364,14 +415,14 @@ if_anchor_lookup_by_address (struct in_addr src) /* Lookup interface by prefix */ struct interface * -if_lookup_prefix (struct prefix *prefix) +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 (iflist, node, ifp)) + for (ALL_LIST_ELEMENTS_RO (vrf_iflist (vrf_id), node, ifp)) { for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) { @@ -384,24 +435,42 @@ if_lookup_prefix (struct prefix *prefix) 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 (const char *name) +{ + return if_get_by_name_vrf (name, VRF_DEFAULT); } struct interface * -if_get_by_name_len(const char *name, size_t namelen) +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 ? */ @@ -521,12 +590,12 @@ if_flag_dump (unsigned long flag) static void if_dump (const struct interface *ifp) { - zlog_info ("Interface %s index %d metric %d mtu %d " + zlog_info ("Interface %s vrf %u index %d metric %d mtu %d " #ifdef HAVE_IPV6 "mtu6 %d " #endif /* HAVE_IPV6 */ "%s", - ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, + ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric, ifp->mtu, #ifdef HAVE_IPV6 ifp->mtu6, #endif /* HAVE_IPV6 */ @@ -537,11 +606,15 @@ if_dump (const struct interface *ifp) 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, @@ -601,12 +674,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... */ @@ -615,9 +688,9 @@ 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 */ @@ -629,6 +702,7 @@ DEFUN (interface, { struct interface *ifp; size_t sl; + vrf_id_t vrf_id = VRF_DEFAULT; if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ) { @@ -638,10 +712,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; @@ -650,6 +727,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", @@ -659,8 +743,12 @@ DEFUN_NOSH (no_interface, { // deleting interface struct interface *ifp; + vrf_id_t vrf_id = VRF_DEFAULT; + + if (argc > 1) + VTY_GET_INTEGER ("VRF ID", vrf_id, argv[1]); - ifp = if_lookup_by_name (argv[0]); + ifp = if_lookup_by_name_vrf (argv[0], vrf_id); if (ifp == NULL) { @@ -680,6 +768,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, @@ -692,8 +788,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)) { @@ -707,6 +807,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) @@ -773,8 +919,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); @@ -1004,35 +1150,36 @@ ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex) /* 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; } @@ -145,6 +145,8 @@ struct interface #ifdef HAVE_NET_RT_IFLIST struct if_data stats; #endif /* HAVE_NET_RT_IFLIST */ + + vrf_id_t vrf_id; }; /* Connected address structure. */ @@ -271,17 +273,38 @@ extern struct interface *if_lookup_address (void *matchaddr, int family); extern struct interface *if_lookup_prefix (struct prefix *prefix); extern struct connected *if_anchor_lookup_by_address (struct in_addr src); +extern struct interface *if_create_vrf (const char *name, int namelen, + vrf_id_t vrf_id); +extern struct interface *if_lookup_by_index_vrf (unsigned int, + vrf_id_t vrf_id); +extern struct interface *if_lookup_exact_address_vrf (void *matchaddr, int family, + vrf_id_t vrf_id); +extern struct interface *if_lookup_address_vrf (void *matchaddr, int family, + vrf_id_t vrf_id); +extern struct interface *if_lookup_prefix_vrf (struct prefix *prefix, + vrf_id_t vrf_id); + /* These 2 functions are to be used when the ifname argument is terminated by a '\0' character: */ extern struct interface *if_lookup_by_name (const char *ifname); extern struct interface *if_get_by_name (const char *ifname); +extern struct interface *if_lookup_by_name_vrf (const char *ifname, + vrf_id_t vrf_id); +extern struct interface *if_get_by_name_vrf (const char *ifname, + vrf_id_t vrf_id); + /* For these 2 functions, the namelen argument should be the precise length of the ifname string (not counting any optional trailing '\0' character). In most cases, strnlen should be used to calculate the namelen value. */ extern struct interface *if_lookup_by_name_len(const char *ifname, - size_t namelen); -extern struct interface *if_get_by_name_len(const char *ifname, size_t namelen); + size_t namelen); +extern struct interface *if_get_by_name_len(const char *ifname,size_t namelen); + +extern struct interface *if_lookup_by_name_len_vrf(const char *ifname, + size_t namelen, vrf_id_t vrf_id); +extern struct interface *if_get_by_name_len_vrf(const char *ifname, + size_t namelen, vrf_id_t vrf_id); /* Delete the interface, but do not free the structure, and leave it in the @@ -302,8 +325,8 @@ extern int if_is_broadcast (struct interface *); extern int if_is_pointopoint (struct interface *); extern int if_is_multicast (struct interface *); extern void if_add_hook (int, int (*)(struct interface *)); -extern void if_init (void); -extern void if_terminate (void); +extern void if_init (vrf_id_t, struct list **); +extern void if_terminate (vrf_id_t, struct list **); extern void if_dump_all (void); extern const char *if_flag_dump(unsigned long); @@ -311,11 +334,13 @@ extern const char *if_flag_dump(unsigned long); ifindex2ifname uses internal interface info, whereas if_indextoname must make a system call. */ extern const char *ifindex2ifname (unsigned int); +extern const char *ifindex2ifname_vrf (unsigned int, vrf_id_t vrf_id); /* Please use ifname2ifindex instead of if_nametoindex where possible; ifname2ifindex uses internal interface info, whereas if_nametoindex must make a system call. */ extern unsigned int ifname2ifindex(const char *ifname); +extern unsigned int ifname2ifindex_vrf(const char *ifname, vrf_id_t vrf_id); /* Connected address functions. */ extern struct connected *connected_new (void); @@ -345,8 +370,12 @@ extern struct cmd_element interface_desc_cmd; extern struct cmd_element no_interface_desc_cmd; extern struct cmd_element interface_cmd; extern struct cmd_element no_interface_cmd; +extern struct cmd_element interface_vrf_cmd; +extern struct cmd_element no_interface_vrf_cmd; extern struct cmd_element interface_pseudo_cmd; extern struct cmd_element no_interface_pseudo_cmd; extern struct cmd_element show_address_cmd; +extern struct cmd_element show_address_vrf_cmd; +extern struct cmd_element show_address_vrf_all_cmd; #endif /* _ZEBRA_IF_H */ diff --git a/lib/memory.c b/lib/memory.c index a9149e10ff..172ddfc49c 100644 --- a/lib/memory.c +++ b/lib/memory.c @@ -437,41 +437,28 @@ memory_init (void) const char * mtype_memstr (char *buf, size_t len, unsigned long bytes) { - unsigned int t, g, m, k; - + unsigned int m, k; + /* easy cases */ if (!bytes) return "0 bytes"; if (bytes == 1) return "1 byte"; - - if (sizeof (unsigned long) >= 8) - /* Hacked to make it not warn on ILP32 machines - * Shift will always be 40 at runtime. See below too */ - t = bytes >> (sizeof (unsigned long) >= 8 ? 40 : 0); - else - t = 0; - g = bytes >> 30; + + /* + * When we pass the 2gb barrier mallinfo() can no longer report + * correct data so it just does something odd... + * Reporting like Terrabytes of data. Which makes users... + * edgy.. yes edgy that's the term for it. + * So let's just give up gracefully + */ + if (bytes > 0x7fffffff) + return "> 2GB"; + m = bytes >> 20; k = bytes >> 10; - - if (t > 10) - { - /* The shift will always be 39 at runtime. - * Just hacked to make it not warn on 'smaller' machines. - * Static compiler analysis should mean no extra code - */ - if (bytes & (1UL << (sizeof (unsigned long) >= 8 ? 39 : 0))) - t++; - snprintf (buf, len, "%4d TiB", t); - } - else if (g > 10) - { - if (bytes & (1 << 29)) - g++; - snprintf (buf, len, "%d GiB", g); - } - else if (m > 10) + + if (m > 10) { if (bytes & (1 << 19)) m++; diff --git a/lib/memtypes.c b/lib/memtypes.c index 03a5c3dcfd..828820f309 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -73,14 +73,15 @@ struct memory_list memory_list_lib[] = { MTYPE_PQUEUE_DATA, "Priority queue data" }, { MTYPE_HOST, "Host config" }, { MTYPE_BFD_INFO, "BFD info" }, + { MTYPE_VRF, "VRF" }, + { MTYPE_VRF_NAME, "VRF name" }, { -1, NULL }, }; struct memory_list memory_list_zebra[] = { { MTYPE_RTADV_PREFIX, "Router Advertisement Prefix" }, - { MTYPE_VRF, "VRF" }, - { MTYPE_VRF_NAME, "VRF name" }, + { MTYPE_ZEBRA_VRF, "ZEBRA VRF" }, { MTYPE_NEXTHOP, "Nexthop" }, { MTYPE_RIB, "RIB" }, { MTYPE_RIB_QUEUE, "RIB process work queue" }, @@ -88,6 +89,7 @@ struct memory_list memory_list_zebra[] = { MTYPE_RIB_DEST, "RIB destination" }, { MTYPE_RIB_TABLE_INFO, "RIB table info" }, { MTYPE_RNH, "Nexthop tracking object" }, + { MTYPE_NETLINK_NAME, "Netlink name" }, { -1, NULL }, }; diff --git a/lib/prefix.c b/lib/prefix.c index 739764842d..43331d1552 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -766,14 +766,15 @@ str2prefix (const char *str, struct prefix *p) return 0; } -int -prefix2str (const struct prefix *p, char *str, int size) +const char * +prefix2str (union prefix46constptr pu, char *str, int size) { + const struct prefix *p = pu.p; char buf[BUFSIZ]; inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ); snprintf (str, size, "%s/%d", buf, p->prefixlen); - return 0; + return str; } struct prefix * diff --git a/lib/prefix.h b/lib/prefix.h index cc4bbe280d..7fef37e3ff 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -179,7 +179,7 @@ extern void prefix_free (struct prefix *); extern const char *prefix_family_str (const struct prefix *); extern int prefix_blen (const struct prefix *); extern int str2prefix (const char *, struct prefix *); -extern int prefix2str (const struct prefix *, char *, int); +extern const char *prefix2str (union prefix46constptr, char *, int); extern int prefix_match (const struct prefix *, const struct prefix *); extern int prefix_same (const struct prefix *, const struct prefix *); extern int prefix_cmp (const struct prefix *, const struct prefix *); diff --git a/lib/routemap.c b/lib/routemap.c index 8e5064b00b..e760dacf7d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -66,6 +66,38 @@ struct route_map_list /* Master list of route map. */ static struct route_map_list route_map_master = { NULL, NULL, NULL, NULL, NULL }; +struct hash *route_map_master_hash = NULL; + +static unsigned int +route_map_hash_key_make (void *p) +{ + const struct route_map *map = p; + return string_hash_make (map->name); +} + +static int +route_map_hash_cmp(const void *p1, const void *p2) +{ + const struct route_map *map1 = p1; + const struct route_map *map2 = p2; + + if (map1->deleted == map2->deleted) + { + if (map1->name && map2->name) + { + if (!strcmp (map1->name, map2->name)) + { + return 1; + } + } + else if (!map1->name && !map2->name) + { + return 1; + } + } + + return 0; +} enum route_map_upd8_type { @@ -127,7 +159,10 @@ route_map_add (const char *name) map = route_map_new (name); list = &route_map_master; - + + /* Add map to the hash */ + hash_get(route_map_master_hash, map, hash_alloc_intern); + map->next = NULL; map->prev = list->tail; if (list->tail) @@ -172,6 +207,7 @@ route_map_free_map (struct route_map *map) else list->head = map->next; + hash_release(route_map_master_hash, map); XFREE (MTYPE_ROUTE_MAP_NAME, map->name); XFREE (MTYPE_ROUTE_MAP, map); } @@ -211,14 +247,17 @@ struct route_map * route_map_lookup_by_name (const char *name) { struct route_map *map; + struct route_map tmp_map; if (!name) return NULL; - for (map = route_map_master.head; map; map = map->next) - if ((strcmp (map->name, name) == 0) && (!map->deleted)) - return map; - return NULL; + // map.deleted is 0 via memset + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + return map; } int @@ -226,17 +265,30 @@ route_map_mark_updated (const char *name, int del_later) { struct route_map *map; int ret = -1; + struct route_map tmp_map; - /* We need to do this walk manually instead of calling lookup_by_name() - * because the lookup function doesn't return route maps marked as - * deleted. + if (!name) + return (ret); + + map = route_map_lookup_by_name(name); + + /* If we did not find the routemap with deleted=0 try again + * with deleted=1 */ - for (map = route_map_master.head; map; map = map->next) - if (strcmp (map->name, name) == 0) - { - map->to_be_processed = 1; - ret = 0; - } + if (!map) + { + memset(&tmp_map, 0, sizeof(struct route_map)); + tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); + tmp_map.deleted = 1; + map = hash_lookup(route_map_master_hash, &tmp_map); + XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); + } + + if (map) + { + map->to_be_processed = 1; + ret = 0; + } return(ret); } @@ -386,8 +438,12 @@ vty_show_route_map (struct vty *vty, const char *name) } else { - vty_out (vty, "%%route-map %s not found%s", name, VTY_NEWLINE); - return CMD_WARNING; + if (zlog_default) + vty_out (vty, "%s", zlog_proto_names[zlog_default->protocol]); + if (zlog_default->instance) + vty_out (vty, " %d", zlog_default->instance); + vty_out (vty, ": 'route-map %s' not found%s", name, VTY_NEWLINE); + return CMD_SUCCESS; } } else @@ -1049,6 +1105,7 @@ route_map_init (void) /* Make vector for match and set. */ route_match_vec = vector_init (1); route_set_vec = vector_init (1); + route_map_master_hash = hash_create(route_map_hash_key_make, route_map_hash_cmp); } void diff --git a/lib/vrf.c b/lib/vrf.c new file mode 100644 index 0000000000..d11a98264c --- /dev/null +++ b/lib/vrf.c @@ -0,0 +1,401 @@ +/* + * VRF functions. + * Copyright (C) 2014 6WIND S.A. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <zebra.h> + +#include "if.h" +#include "vrf.h" +#include "prefix.h" +#include "table.h" +#include "log.h" +#include "memory.h" + +#define VRF_DEFAULT_NAME "Default-IP-Routing-Table" + +struct vrf +{ + /* Identifier, same as the vector index */ + vrf_id_t vrf_id; + /* Name */ + char *name; + + /* Master list of interfaces belonging to this VRF */ + struct list *iflist; + + /* User data */ + void *info; +}; + +/* Holding VRF hooks */ +struct vrf_master +{ + int (*vrf_new_hook) (vrf_id_t, void **); + int (*vrf_delete_hook) (vrf_id_t, void **); + int (*vrf_enable_hook) (vrf_id_t, void **); + int (*vrf_disable_hook) (vrf_id_t, void **); +} vrf_master = {0,}; + +/* VRF table */ +struct route_table *vrf_table = NULL; + +static int vrf_is_enabled (struct vrf *vrf); +static int vrf_enable (struct vrf *vrf); +static void vrf_disable (struct vrf *vrf); + + +/* Build the table key */ +static void +vrf_build_key (vrf_id_t vrf_id, struct prefix *p) +{ + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4.s_addr = vrf_id; +} + +/* Get a VRF. If not found, create one. */ +static struct vrf * +vrf_get (vrf_id_t vrf_id) +{ + struct prefix p; + struct route_node *rn; + struct vrf *vrf; + + vrf_build_key (vrf_id, &p); + rn = route_node_get (vrf_table, &p); + if (rn->info) + { + vrf = (struct vrf *)rn->info; + route_unlock_node (rn); /* get */ + return vrf; + } + + vrf = XCALLOC (MTYPE_VRF, sizeof (struct vrf)); + vrf->vrf_id = vrf_id; + rn->info = vrf; + + /* Initialize interfaces. */ + if_init (vrf_id, &vrf->iflist); + + zlog_info ("VRF %u is created.", vrf_id); + + if (vrf_master.vrf_new_hook) + (*vrf_master.vrf_new_hook) (vrf_id, &vrf->info); + + return vrf; +} + +/* Delete a VRF. This is called in vrf_terminate(). */ +static void +vrf_delete (struct vrf *vrf) +{ + zlog_info ("VRF %u is to be deleted.", vrf->vrf_id); + + if (vrf_is_enabled (vrf)) + vrf_disable (vrf); + + if (vrf_master.vrf_delete_hook) + (*vrf_master.vrf_delete_hook) (vrf->vrf_id, &vrf->info); + + if_terminate (vrf->vrf_id, &vrf->iflist); + + if (vrf->name) + XFREE (MTYPE_VRF_NAME, vrf->name); + + XFREE (MTYPE_VRF, vrf); +} + +/* Look up a VRF by identifier. */ +static struct vrf * +vrf_lookup (vrf_id_t vrf_id) +{ + struct prefix p; + struct route_node *rn; + struct vrf *vrf = NULL; + + vrf_build_key (vrf_id, &p); + rn = route_node_lookup (vrf_table, &p); + if (rn) + { + vrf = (struct vrf *)rn->info; + route_unlock_node (rn); /* lookup */ + } + return vrf; +} + +/* + * Check whether the VRF is enabled - that is, whether the VRF + * is ready to allocate resources. Currently there's only one + * type of resource: socket. + */ +static int +vrf_is_enabled (struct vrf *vrf) +{ + return vrf && vrf->vrf_id == VRF_DEFAULT; +} + +/* + * Enable a VRF - that is, let the VRF be ready to use. + * The VRF_ENABLE_HOOK callback will be called to inform + * that they can allocate resources in this VRF. + * + * RETURN: 1 - enabled successfully; otherwise, 0. + */ +static int +vrf_enable (struct vrf *vrf) +{ + /* Till now, only the default VRF can be enabled. */ + if (vrf->vrf_id == VRF_DEFAULT) + { + zlog_info ("VRF %u is enabled.", vrf->vrf_id); + + if (vrf_master.vrf_enable_hook) + (*vrf_master.vrf_enable_hook) (vrf->vrf_id, &vrf->info); + + return 1; + } + + return 0; +} + +/* + * Disable a VRF - that is, let the VRF be unusable. + * The VRF_DELETE_HOOK callback will be called to inform + * that they must release the resources in the VRF. + */ +static void +vrf_disable (struct vrf *vrf) +{ + if (vrf_is_enabled (vrf)) + { + zlog_info ("VRF %u is to be disabled.", vrf->vrf_id); + + /* Till now, nothing to be done for the default VRF. */ + + if (vrf_master.vrf_disable_hook) + (*vrf_master.vrf_disable_hook) (vrf->vrf_id, &vrf->info); + } +} + + +/* Add a VRF hook. Please add hooks before calling vrf_init(). */ +void +vrf_add_hook (int type, int (*func)(vrf_id_t, void **)) +{ + switch (type) { + case VRF_NEW_HOOK: + vrf_master.vrf_new_hook = func; + break; + case VRF_DELETE_HOOK: + vrf_master.vrf_delete_hook = func; + break; + case VRF_ENABLE_HOOK: + vrf_master.vrf_enable_hook = func; + break; + case VRF_DISABLE_HOOK: + vrf_master.vrf_disable_hook = func; + break; + default: + break; + } +} + +/* Return the iterator of the first VRF. */ +vrf_iter_t +vrf_first (void) +{ + struct route_node *rn; + + for (rn = route_top (vrf_table); rn; rn = route_next (rn)) + if (rn->info) + { + route_unlock_node (rn); /* top/next */ + return (vrf_iter_t)rn; + } + return VRF_ITER_INVALID; +} + +/* Return the next VRF iterator to the given iterator. */ +vrf_iter_t +vrf_next (vrf_iter_t iter) +{ + struct route_node *rn = NULL; + + /* Lock it first because route_next() will unlock it. */ + if (iter != VRF_ITER_INVALID) + rn = route_next (route_lock_node ((struct route_node *)iter)); + + for (; rn; rn = route_next (rn)) + if (rn->info) + { + route_unlock_node (rn); /* next */ + return (vrf_iter_t)rn; + } + return VRF_ITER_INVALID; +} + +/* Return the VRF iterator of the given VRF ID. If it does not exist, + * the iterator of the next existing VRF is returned. */ +vrf_iter_t +vrf_iterator (vrf_id_t vrf_id) +{ + struct prefix p; + struct route_node *rn; + + vrf_build_key (vrf_id, &p); + rn = route_node_get (vrf_table, &p); + if (rn->info) + { + /* OK, the VRF exists. */ + route_unlock_node (rn); /* get */ + return (vrf_iter_t)rn; + } + + /* Find the next VRF. */ + for (rn = route_next (rn); rn; rn = route_next (rn)) + if (rn->info) + { + route_unlock_node (rn); /* next */ + return (vrf_iter_t)rn; + } + + return VRF_ITER_INVALID; +} + +/* Obtain the VRF ID from the given VRF iterator. */ +vrf_id_t +vrf_iter2id (vrf_iter_t iter) +{ + struct route_node *rn = (struct route_node *) iter; + return (rn && rn->info) ? ((struct vrf *)rn->info)->vrf_id : VRF_DEFAULT; +} + +/* Obtain the data pointer from the given VRF iterator. */ +void * +vrf_iter2info (vrf_iter_t iter) +{ + struct route_node *rn = (struct route_node *) iter; + return (rn && rn->info) ? ((struct vrf *)rn->info)->info : NULL; +} + +/* Obtain the interface list from the given VRF iterator. */ +struct list * +vrf_iter2iflist (vrf_iter_t iter) +{ + struct route_node *rn = (struct route_node *) iter; + return (rn && rn->info) ? ((struct vrf *)rn->info)->iflist : NULL; +} + +/* Get the data pointer of the specified VRF. If not found, create one. */ +void * +vrf_info_get (vrf_id_t vrf_id) +{ + struct vrf *vrf = vrf_get (vrf_id); + return vrf->info; +} + +/* Look up the data pointer of the specified VRF. */ +void * +vrf_info_lookup (vrf_id_t vrf_id) +{ + struct vrf *vrf = vrf_lookup (vrf_id); + return vrf ? vrf->info : NULL; +} + +/* Look up the interface list in a VRF. */ +struct list * +vrf_iflist (vrf_id_t vrf_id) +{ + struct vrf * vrf = vrf_lookup (vrf_id); + return vrf ? vrf->iflist : NULL; +} + +/* Get the interface list of the specified VRF. Create one if not find. */ +struct list * +vrf_iflist_get (vrf_id_t vrf_id) +{ + struct vrf * vrf = vrf_get (vrf_id); + return vrf->iflist; +} + +/* Initialize VRF module. */ +void +vrf_init (void) +{ + struct vrf *default_vrf; + + /* Allocate VRF table. */ + vrf_table = route_table_init (); + + /* The default VRF always exists. */ + default_vrf = vrf_get (VRF_DEFAULT); + if (!default_vrf) + { + zlog_err ("vrf_init: failed to create the default VRF!"); + exit (1); + } + + /* Set the default VRF name. */ + default_vrf->name = XSTRDUP (MTYPE_VRF_NAME, VRF_DEFAULT_NAME); + + /* Enable the default VRF. */ + if (!vrf_enable (default_vrf)) + { + zlog_err ("vrf_init: failed to enable the default VRF!"); + exit (1); + } +} + +/* Terminate VRF module. */ +void +vrf_terminate (void) +{ + struct route_node *rn; + struct vrf *vrf; + + for (rn = route_top (vrf_table); rn; rn = route_next (rn)) + if ((vrf = rn->info) != NULL) + vrf_delete (vrf); + + route_table_finish (vrf_table); + vrf_table = NULL; +} + +/* Create a socket for the VRF. */ +int +vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id) +{ + int ret = -1; + + if (!vrf_is_enabled (vrf_lookup (vrf_id))) + { + errno = ENOSYS; + return -1; + } + + if (vrf_id == VRF_DEFAULT) + ret = socket (domain, type, protocol); + else + errno = ENOSYS; + + return ret; +} + diff --git a/lib/vrf.h b/lib/vrf.h new file mode 100644 index 0000000000..653fabf905 --- /dev/null +++ b/lib/vrf.h @@ -0,0 +1,127 @@ +/* + * VRF related header. + * Copyright (C) 2014 6WIND S.A. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2, or (at your + * option) any later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ZEBRA_VRF_H +#define _ZEBRA_VRF_H + +#include "linklist.h" + +/* The default VRF ID */ +#define VRF_DEFAULT 0 + +/* + * The command strings + */ + +#define VRF_CMD_STR "vrf <0-65535>" +#define VRF_CMD_HELP_STR "Specify the VRF\nThe VRF ID\n" + +#define VRF_ALL_CMD_STR "vrf all" +#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n" + +/* + * VRF hooks + */ + +#define VRF_NEW_HOOK 0 /* a new VRF is just created */ +#define VRF_DELETE_HOOK 1 /* a VRF is to be deleted */ +#define VRF_ENABLE_HOOK 2 /* a VRF is ready to use */ +#define VRF_DISABLE_HOOK 3 /* a VRF is to be unusable */ + +/* + * Add a specific hook to VRF module. + * @param1: hook type + * @param2: the callback function + * - param 1: the VRF ID + * - param 2: the address of the user data pointer (the user data + * can be stored in or freed from there) + */ +extern void vrf_add_hook (int, int (*)(vrf_id_t, void **)); + +/* + * VRF iteration + */ + +typedef void * vrf_iter_t; +#define VRF_ITER_INVALID NULL /* invalid value of the iterator */ + +/* + * VRF iteration utilities. Example for the usage: + * + * vrf_iter_t iter = vrf_first(); + * for (; iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + * + * or + * + * vrf_iter_t iter = vrf_iterator (<a given VRF ID>); + * for (; iter != VRF_ITER_INVALID; iter = vrf_next (iter)) + */ + +/* Return the iterator of the first VRF. */ +extern vrf_iter_t vrf_first (void); +/* Return the next VRF iterator to the given iterator. */ +extern vrf_iter_t vrf_next (vrf_iter_t); +/* Return the VRF iterator of the given VRF ID. If it does not exist, + * the iterator of the next existing VRF is returned. */ +extern vrf_iter_t vrf_iterator (vrf_id_t); + +/* + * VRF iterator to properties + */ +extern vrf_id_t vrf_iter2id (vrf_iter_t); +extern void *vrf_iter2info (vrf_iter_t); +extern struct list *vrf_iter2iflist (vrf_iter_t); + +/* + * Utilities to obtain the user data + */ + +/* Get the data pointer of the specified VRF. If not found, create one. */ +extern void *vrf_info_get (vrf_id_t); +/* Look up the data pointer of the specified VRF. */ +extern void *vrf_info_lookup (vrf_id_t); + +/* + * Utilities to obtain the interface list + */ + +/* Look up the interface list of the specified VRF. */ +extern struct list *vrf_iflist (vrf_id_t); +/* Get the interface list of the specified VRF. Create one if not find. */ +extern struct list *vrf_iflist_get (vrf_id_t); + +/* + * VRF initializer/destructor + */ +/* Please add hooks before calling vrf_init(). */ +extern void vrf_init (void); +extern void vrf_terminate (void); + +/* + * VRF utilities + */ + +/* Create a socket serving for the given VRF */ +extern int vrf_socket (int, int, int, vrf_id_t); + +#endif /*_ZEBRA_VRF_H*/ + diff --git a/lib/zebra.h b/lib/zebra.h index 0a1dd7f46c..a3ac78cbce 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -556,6 +556,9 @@ typedef u_int8_t safi_t; typedef u_int16_t zebra_size_t; typedef u_int16_t zebra_command_t; +/* VRF ID type. */ +typedef u_int16_t vrf_id_t; + /* FIFO -- first in first out structure and macros. */ struct fifo { |
