diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/connected.c | 24 | ||||
-rw-r--r-- | zebra/connected.h | 4 | ||||
-rw-r--r-- | zebra/debug.c | 4 | ||||
-rw-r--r-- | zebra/if_netlink.c | 5 | ||||
-rw-r--r-- | zebra/interface.c | 31 | ||||
-rw-r--r-- | zebra/irdp_packet.c | 2 | ||||
-rw-r--r-- | zebra/kernel_null.c | 6 | ||||
-rw-r--r-- | zebra/kernel_socket.h | 4 | ||||
-rw-r--r-- | zebra/main.c | 12 | ||||
-rw-r--r-- | zebra/rib.h | 68 | ||||
-rw-r--r-- | zebra/rt.h | 4 | ||||
-rw-r--r-- | zebra/rt_ioctl.c | 4 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 379 | ||||
-rw-r--r-- | zebra/rt_socket.c | 4 | ||||
-rw-r--r-- | zebra/rtadv.c | 16 | ||||
-rw-r--r-- | zebra/rtadv.h | 3 | ||||
-rw-r--r-- | zebra/rtread_netlink.c | 6 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 534 | ||||
-rw-r--r-- | zebra/zebra_vty.c | 4 | ||||
-rw-r--r-- | zebra/zserv.c | 6 |
20 files changed, 525 insertions, 595 deletions
diff --git a/zebra/connected.c b/zebra/connected.c index ad3e9607..b235d8c0 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -36,6 +36,7 @@ #include "zebra/interface.h" #include "zebra/connected.h" extern struct zebra_t zebrad; + /* withdraw a connected address */ static void @@ -86,7 +87,7 @@ connected_announce (struct interface *ifp, struct connected *ifc) zebra_interface_address_add_update (ifp, ifc); - if (if_is_up(ifp)) + if (if_is_operative(ifp)) { if (ifc->address->family == AF_INET) connected_up_ipv4 (ifp, ifc); @@ -174,6 +175,7 @@ void connected_up_ipv4 (struct interface *ifp, struct connected *ifc) { struct prefix_ipv4 p; + struct in_addr src = ((struct prefix_ipv4 *) ifc->address)->prefix; if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) return; @@ -188,14 +190,14 @@ connected_up_ipv4 (struct interface *ifp, struct connected *ifc) if (prefix_ipv4_any (&p)) return; - rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex, - RT_TABLE_MAIN, ifp->metric, 0); + rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, &src, + ifp->ifindex, RT_TABLE_MAIN, ifp->metric, 0, RT_SCOPE_LINK); rib_update (); } /* Add connected IPv4 route to the interface. */ -void +struct connected * connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, u_char prefixlen, struct in_addr *broad, const char *label) @@ -270,10 +272,10 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); /* nothing to do? */ - if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) - return; - + ifc = connected_implicit_withdraw (ifp, ifc); connected_announce (ifp, ifc); + + return ifc; } void @@ -347,7 +349,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc) } /* Add connected IPv6 route to the interface. */ -void +struct connected * connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) @@ -394,10 +396,10 @@ connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); - if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) - return; - + ifc = connected_implicit_withdraw (ifp, ifc); connected_announce (ifp, ifc); + + return ifc; } void diff --git a/zebra/connected.h b/zebra/connected.h index 9595ddb1..8bfe4118 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -26,7 +26,7 @@ extern struct connected * connected_check (struct interface *ifp, struct prefix *p); -extern void +extern struct connected * connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, u_char prefixlen, struct in_addr *broad, const char *label); @@ -39,7 +39,7 @@ extern void connected_up_ipv4 (struct interface *, struct connected *); extern void connected_down_ipv4 (struct interface *, struct connected *); #ifdef HAVE_IPV6 -extern void +extern struct connected * connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *address, u_char prefixlen, struct in6_addr *broad, const char *label); diff --git a/zebra/debug.c b/zebra/debug.c index 7350e576..175029b8 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -236,11 +236,7 @@ DEFUN (no_debug_zebra_rib, DEFUN (no_debug_zebra_rib_q, no_debug_zebra_rib_q_cmd, -<<<<<<< HEAD:zebra/debug.c - "no debug zebra rib queueu", -======= "no debug zebra rib queue", ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/debug.c NO_STR DEBUG_STR "Zebra configuration\n" diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c9c14760..701c81b6 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -22,12 +22,11 @@ #include <zebra.h> -/* Extern from rt_netlink.c */ -void interface_lookup_netlink (); +extern int interface_lookup_netlink (void); /* Interface information read by netlink. */ void -interface_list () +interface_list (void) { interface_lookup_netlink (); } diff --git a/zebra/interface.c b/zebra/interface.c index 184b42a0..74c977a9 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -48,8 +48,7 @@ if_zebra_new_hook (struct interface *ifp) { struct zebra_if *zebra_if; - zebra_if = XMALLOC (MTYPE_TMP, sizeof (struct zebra_if)); - memset (zebra_if, 0, sizeof (struct zebra_if)); + zebra_if = XCALLOC (MTYPE_TMP, sizeof (struct zebra_if)); zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_UNSPEC; @@ -274,7 +273,7 @@ if_addr_wakeup (struct interface *ifp) /* Address check. */ if (p->family == AF_INET) { - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { /* XXX: WTF is it trying to set flags here? * caller has just gotten a new interface, has been @@ -311,7 +310,7 @@ if_addr_wakeup (struct interface *ifp) #ifdef HAVE_IPV6 if (p->family == AF_INET6) { - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { /* XXX: See long comment above */ if_set_flags (ifp, IFF_UP | IFF_RUNNING); @@ -379,7 +378,7 @@ if_delete_update (struct interface *ifp) zebra_if = ifp->info; - if (if_is_up(ifp)) + if (if_is_operative(ifp)) { zlog_err ("interface %s index %d is still up while being deleted.", ifp->name, ifp->ifindex); @@ -538,15 +537,25 @@ if_down (struct interface *ifp) if (p->family == AF_INET) connected_down_ipv4 (ifp, ifc); + } + } + + /* Examine all static routes which direct to the interface. */ + rib_update (); + #ifdef HAVE_IPV6 - else if (p->family == AF_INET6) + if (ifp->connected) + { + for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc)) + { + p = ifc->address; + if (p->family == AF_INET6) connected_down_ipv6 (ifp, ifc); -#endif /* HAVE_IPV6 */ } } - /* Examine all static routes which direct to the interface. */ rib_update (); +#endif /* HAVE_IPV6 */ } void @@ -822,6 +831,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) #endif /* HAVE_NET_RT_IFLIST */ } +#if 0 /* Check supported address family. */ static int if_supported_family (int family) @@ -834,6 +844,7 @@ if_supported_family (int family) #endif /* HAVE_IPV6 */ return 0; } +#endif /* Wrapper hook point for zebra daemon so that ifindex can be set * DEFUN macro not used as extract.pl HAS to ignore this @@ -1205,7 +1216,7 @@ ip_address_install (struct vty *vty, struct interface *ifp, && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); @@ -1398,7 +1409,7 @@ ipv6_address_install (struct vty *vty, struct interface *ifp, && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 3c5f1559..ae121ea1 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -231,7 +231,7 @@ int irdp_read_raw(struct thread *r) struct zebra_if *zi; struct irdp_interface *irdp; char buf[IRDP_RX_BUF]; - int ret, ifindex; + int ret, ifindex = 0; int irdp_sock = THREAD_FD (r); t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock); diff --git a/zebra/kernel_null.c b/zebra/kernel_null.c index 94b7b3c7..c72bbd09 100644 --- a/zebra/kernel_null.c +++ b/zebra/kernel_null.c @@ -12,9 +12,9 @@ int kernel_add_ipv4 (struct prefix *a, struct rib *b) { return 0; } #pragma weak kernel_delete_ipv4 = kernel_add_ipv4 int kernel_add_ipv6 (struct prefix *a, struct rib *b) { return 0; } #pragma weak kernel_delete_ipv6 = kernel_add_ipv6 -int kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table) -{ return 0; } +void kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, + unsigned int index, int table) +{ } int kernel_add_route (struct prefix_ipv4 *a, struct in_addr *b, int c, int d) { return 0; } diff --git a/zebra/kernel_socket.h b/zebra/kernel_socket.h index ad6770ca..e9558ad6 100644 --- a/zebra/kernel_socket.h +++ b/zebra/kernel_socket.h @@ -28,10 +28,6 @@ extern int ifam_read (struct ifa_msghdr *); extern int ifm_read (struct if_msghdr *); extern int rtm_write (int, union sockunion *, union sockunion *, union sockunion *, unsigned int, int, int); -<<<<<<< HEAD:zebra/kernel_socket.h -extern struct message rtm_type_str[]; -======= extern const struct message rtm_type_str[]; ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/kernel_socket.h #endif /* __ZEBRA_KERNEL_SOCKET_H */ diff --git a/zebra/main.c b/zebra/main.c index 61750f1d..ac0637b6 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -63,12 +63,16 @@ int keep_kernel_mode = 0; u_int32_t nl_rcvbufsize = 0; #endif /* HAVE_NETLINK */ +/* Manage system routes. */ +extern int rib_system_routes; + /* Command line options. */ struct option longopts[] = { { "batch", no_argument, NULL, 'b'}, { "daemon", no_argument, NULL, 'd'}, { "keep_kernel", no_argument, NULL, 'k'}, + { "rib_system", no_argument, NULL, 'S'}, { "log_mode", no_argument, NULL, 'l'}, { "config_file", required_argument, NULL, 'f'}, { "pid_file", required_argument, NULL, 'i'}, @@ -131,6 +135,7 @@ usage (char *progname, int status) "-i, --pid_file Set process identifier file name\n"\ "-k, --keep_kernel Don't delete old routes which installed by "\ "zebra.\n"\ + "-S, --system Manage all routes on link transistions\n" "-l, --log_mode Set verbose log mode flag\n"\ "-C, --dryrun Check configuration for validity and exit\n"\ "-A, --vty_addr Set vty's bind address\n"\ @@ -231,9 +236,9 @@ main (int argc, char **argv) int opt; #ifdef HAVE_NETLINK - opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vs:C", longopts, 0); + opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vs:CS", longopts, 0); #else - opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vC", longopts, 0); + opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vCS", longopts, 0); #endif /* HAVE_NETLINK */ if (opt == EOF) @@ -251,6 +256,9 @@ main (int argc, char **argv) case 'k': keep_kernel_mode = 1; break; + case 'S': + rib_system_routes = 1; + break; case 'C': dryrun = 1; break; diff --git a/zebra/rib.h b/zebra/rib.h index 887ed3c2..c39afa73 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -38,10 +38,6 @@ union g_addr { struct rib { - /* Status Flags for the *route_node*, but kept in the head RIB.. */ - u_char rn_status; -#define RIB_ROUTE_QUEUED(x) (1 << (x)) - /* Link list. */ struct rib *next; struct rib *prev; @@ -49,20 +45,27 @@ struct rib /* Nexthop structure */ struct nexthop *nexthop; - /* Refrence count. */ + /* Reference count. */ unsigned long refcnt; /* Uptime. */ time_t uptime; - /* Type fo this route. */ - int type; + /* Metric */ + u_int32_t metric; /* Which routing table */ - int table; + u_int32_t table; - /* Metric */ - u_int32_t metric; + /* Type for this route. < ZEBRA_ROUTE_MAX */ + u_int8_t type; + + /* Scope for this route. */ + u_int8_t scope; + + /* Status Flags for the *route_node*, but kept in the head RIB.. */ + u_char rn_status; +#define RIB_ROUTE_QUEUED(x) (1 << (x)) /* Distance. */ u_char distance; @@ -76,6 +79,7 @@ struct rib /* RIB internal status */ u_char status; #define RIB_ENTRY_REMOVED (1 << 0) +#define RIB_ENTRY_PRESERVE (2 << 0) /* Nexthop information. */ u_char nexthop_num; @@ -104,6 +108,13 @@ struct static_ipv4 struct static_ipv4 *prev; struct static_ipv4 *next; + /* Nexthop value. */ + union + { + struct in_addr ipv4; + char *ifname; + } gate; + /* Administrative distance. */ u_char distance; @@ -113,13 +124,6 @@ struct static_ipv4 #define STATIC_IPV4_IFNAME 2 #define STATIC_IPV4_BLACKHOLE 3 - /* Nexthop value. */ - union - { - struct in_addr ipv4; - char *ifname; - } gate; - /* bit flags */ u_char flags; /* @@ -136,6 +140,10 @@ struct static_ipv6 struct static_ipv6 *prev; struct static_ipv6 *next; + /* Nexthop value. */ + struct in6_addr ipv6; + char *ifname; + /* Administrative distance. */ u_char distance; @@ -144,11 +152,6 @@ struct static_ipv6 #define STATIC_IPV6_GATEWAY 1 #define STATIC_IPV6_GATEWAY_IFNAME 2 #define STATIC_IPV6_IFNAME 3 - - /* Nexthop value. */ - struct in6_addr ipv6; - char *ifname; - /* bit flags */ u_char flags; /* @@ -180,22 +183,24 @@ struct nexthop /* Interface index. */ char *ifname; unsigned int ifindex; + + /* Nexthop address or interface name. */ + union g_addr gate; + + unsigned int rifindex; + union g_addr rgate; + union g_addr src; - enum nexthop_types_t type; +/* Really enum nexthop_types_t but safe space */ + u_char type; u_char flags; #define NEXTHOP_FLAG_ACTIVE (1 << 0) /* This nexthop is alive. */ #define NEXTHOP_FLAG_FIB (1 << 1) /* FIB nexthop. */ #define NEXTHOP_FLAG_RECURSIVE (1 << 2) /* Recursive nexthop. */ - /* Nexthop address or interface name. */ - union g_addr gate; - /* Recursive lookup nexthop. */ u_char rtype; - unsigned int rifindex; - union g_addr rgate; - union g_addr src; }; /* Routing table instance. */ @@ -220,7 +225,8 @@ struct vrf struct route_table *stable[AFI_MAX][SAFI_MAX]; }; -extern struct nexthop *nexthop_ifindex_add (struct rib *, unsigned int); +extern struct nexthop *nexthop_ifindex_add (struct rib *, unsigned int, + struct in_addr *); extern struct nexthop *nexthop_ifname_add (struct rib *, char *); extern struct nexthop *nexthop_blackhole_add (struct rib *); extern struct nexthop *nexthop_ipv4_add (struct rib *, struct in_addr *, @@ -249,7 +255,7 @@ extern struct route_table *vrf_static_table (afi_t afi, safi_t safi, u_int32_t i extern int rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, unsigned int ifindex, u_int32_t vrf_id, - u_int32_t, u_char); + u_int32_t metric, u_int8_t distance, u_int8_t scope); extern int rib_add_ipv4_multipath (struct prefix_ipv4 *, struct rib *); @@ -36,8 +36,8 @@ extern int kernel_address_delete_ipv4 (struct interface *, struct connected *); #ifdef HAVE_IPV6 extern int kernel_add_ipv6 (struct prefix *, struct rib *); extern int kernel_delete_ipv6 (struct prefix *, struct rib *); -extern int kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table); +extern void kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, + unsigned int index, int table); #endif /* HAVE_IPV6 */ diff --git a/zebra/rt_ioctl.c b/zebra/rt_ioctl.c index a5d588c7..d39ec4df 100644 --- a/zebra/rt_ioctl.c +++ b/zebra/rt_ioctl.c @@ -553,8 +553,8 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) /* Delete IPv6 route from the kernel. */ int kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table) + unsigned int index, int table) { - return kernel_ioctl_ipv6 (SIOCDELRT, dest, gate, index, flags); + return kernel_ioctl_ipv6 (SIOCDELRT, dest, gate, index, 0; } #endif /* HAVE_IPV6 */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 07e86647..8f8ad58a 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -41,6 +41,7 @@ #include "zebra/redistribute.h" #include "zebra/interface.h" #include "zebra/debug.h" +#include <stddef.h> /* Socket interface to kernel */ struct nlsock @@ -65,7 +66,7 @@ static const struct message nlmsg_str[] = { {0, NULL} }; -static const char *nexthop_types_desc[] = +static const char *nexthop_types_desc[] = { "none", "Directly connected", @@ -85,32 +86,11 @@ extern struct zebra_privs_t zserv_privs; extern u_int32_t nl_rcvbufsize; -/* Note: on netlink systems, there should be a 1-to-1 mapping between interface - names and ifindex values. */ -static void -set_ifindex(struct interface *ifp, unsigned int ifi_index) -{ - struct interface *oifp; +extern int rib_system_routes; - if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp)) - { - if (ifi_index == IFINDEX_INTERNAL) - zlog_err("Netlink is setting interface %s ifindex to reserved " - "internal value %u", ifp->name, ifi_index); - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("interface index %d was renamed from %s to %s", - ifi_index, oifp->name, ifp->name); - if (if_is_up(oifp)) - zlog_err("interface rename detected on up interface: index %d " - "was renamed from %s to %s, results are uncertain!", - ifi_index, oifp->name, ifp->name); - if_delete_update(oifp); - } - } - ifp->ifindex = ifi_index; -} +static void +netlink_delroute (int family, void *dest, int length, void *gate, + int index, int table, int proto); static int netlink_recvbuf (struct nlsock *nl, uint32_t newsize) @@ -280,7 +260,8 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), while (1) { - char buf[4096]; + //increased from 4096 to 32768 as recvmsg overrun error + char buf[32768]; struct iovec iov = { buf, sizeof buf }; struct sockaddr_nl snl; struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 }; @@ -293,6 +274,7 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), continue; if (errno == EWOULDBLOCK || errno == EAGAIN) break; + zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s", nl->name, safe_strerror(errno)); continue; @@ -311,6 +293,13 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return -1; } + /* JF: Ignore messages that aren't from the kernel */ + if ( snl.nl_pid != 0 ) + { + zlog_debug ("Ignoring message from pid %u", snl.nl_pid ); + continue; + } + for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); h = NLMSG_NEXT (h, status)) { @@ -462,14 +451,28 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) #endif /* IFLA_WIRELESS */ if (tb[IFLA_IFNAME] == NULL) - return -1; + { + zlog_err("%s: missing interface name in message", __func__); + return -1; + } name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (ifi->ifi_index == IFINDEX_INTERNAL) + { + zlog_err("%s: reserved ifindex", __func__); + return -1; + } + /* Add interface. */ - ifp = if_get_by_name (name); - set_ifindex(ifp, ifi->ifi_index); + ifp = if_lookup_by_index(ifi->ifi_index); + if (!ifp) + { + ifp = if_create(name, strlen(name)); + ifp->ifindex = ifi->ifi_index; + } + strncpy(ifp->name, name, INTERFACE_NAMSIZ); ifp->flags = ifi->ifi_flags & 0x0000fffff; - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); + ifp->mtu6 = ifp->mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; /* Hardware type and address. */ @@ -523,7 +526,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) #ifdef HAVE_IPV6 && ifa->ifa_family != AF_INET6 #endif /* HAVE_IPV6 */ - ) + ) return 0; if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR) @@ -548,7 +551,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) { char buf[BUFSIZ]; zlog_debug ("netlink_interface_addr %s %s:", - lookup (nlmsg_str, h->nlmsg_type), ifp->name); + lookup (nlmsg_str, h->nlmsg_type), ifp->name); if (tb[IFA_LOCAL]) zlog_debug (" IFA_LOCAL %s/%d", inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]), @@ -614,9 +617,25 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) if (ifa->ifa_family == AF_INET) { if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv4 (ifp, flags, - (struct in_addr *) addr, ifa->ifa_prefixlen, - (struct in_addr *) broad, label); + { + struct connected *ifc; + ifc = connected_add_ipv4 (ifp, flags, + (struct in_addr *) addr, ifa->ifa_prefixlen, + (struct in_addr *) broad, label); + + /* If address added, but interface is down, + then remove the FIB entry from kernel. + */ + if (rib_system_routes && ifc && !if_is_operative (ifp)) + { + struct prefix_ipv4 p; + PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc)); + apply_mask_ipv4 (&p); + + netlink_delroute (p.family, &p.prefix, p.prefixlen, NULL, + ifp->ifindex, RT_TABLE_MAIN, RTPROT_KERNEL); + } + } else connected_delete_ipv4 (ifp, flags, (struct in_addr *) addr, ifa->ifa_prefixlen, @@ -626,9 +645,9 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) if (ifa->ifa_family == AF_INET6) { if (h->nlmsg_type == RTM_NEWADDR) - connected_add_ipv6 (ifp, flags, - (struct in6_addr *) addr, ifa->ifa_prefixlen, - (struct in6_addr *) broad, label); + connected_add_ipv6 (ifp, flags, + (struct in6_addr *) addr, ifa->ifa_prefixlen, + (struct in6_addr *) broad, label); else connected_delete_ipv6 (ifp, (struct in6_addr *) addr, ifa->ifa_prefixlen, @@ -699,7 +718,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) src = NULL; if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); + index = *(uint32_t *) RTA_DATA (tb[RTA_OIF]); if (tb[RTA_DST]) dest = RTA_DATA (tb[RTA_DST]); @@ -714,7 +733,7 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) gate = RTA_DATA (tb[RTA_GATEWAY]); if (tb[RTA_PRIORITY]) - metric = *(int *) RTA_DATA(tb[RTA_PRIORITY]); + metric = *(uint32_t *) RTA_DATA(tb[RTA_PRIORITY]); if (rtm->rtm_family == AF_INET) { @@ -723,7 +742,8 @@ netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) memcpy (&p.prefix, dest, 4); p.prefixlen = rtm->rtm_dst_len; - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, table, metric, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, flags, &p, gate, src, index, + table, metric, 0, rtm->rtm_scope); } #ifdef HAVE_IPV6 if (rtm->rtm_family == AF_INET6) @@ -830,7 +850,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) src = NULL; if (tb[RTA_OIF]) - index = *(int *) RTA_DATA (tb[RTA_OIF]); + index = *(uint32_t *) RTA_DATA (tb[RTA_OIF]); if (tb[RTA_DST]) dest = RTA_DATA (tb[RTA_DST]); @@ -861,7 +881,8 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) } if (h->nlmsg_type == RTM_NEWROUTE) - rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, 0); + rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, src, index, table, 0, + 0, rtm->rtm_scope); else rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table); } @@ -936,66 +957,103 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) #endif /* IFLA_WIRELESS */ if (tb[IFLA_IFNAME] == NULL) - return -1; + { + zlog_err("%s: missing interface name", __func__); + return -1; + } name = (char *) RTA_DATA (tb[IFLA_IFNAME]); /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { - ifp = if_lookup_by_name (name); + unsigned long new_flags = ifi->ifi_flags & 0x0000fffff; + unsigned int mtu = *(uint32_t *) RTA_DATA (tb[IFLA_MTU]); + ifp = if_lookup_by_index (ifi->ifi_index); + /* New interface */ if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) - ifp = if_get_by_name (name); - - set_ifindex(ifp, ifi->ifi_index); - ifp->flags = ifi->ifi_flags & 0x0000fffff; - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 1; - - /* If new link is added. */ - if_add_update (ifp); + { + ifp = if_create(name, strlen(name)); + ifp->ifindex = ifi->ifi_index; + ifp->metric = 1; + } + else if (strcmp(ifp->name, name) != 0) + { + strncpy(ifp->name, name, INTERFACE_NAMSIZ); + } + + zlog_info ("interface %s index %d %s added.", + name, ifi->ifi_index, if_flag_dump(new_flags)); + + ifp->flags = new_flags; + ifp->mtu6 = ifp->mtu = mtu; + + /* If new link is added. */ + if_add_update (ifp); } - else - { - /* Interface status change. */ - set_ifindex(ifp, ifi->ifi_index); - ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); - ifp->metric = 1; - - if (if_is_operative (ifp)) - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (!if_is_operative (ifp)) - if_down (ifp); + /* Interface status change. */ + else if (new_flags != ifp->flags) + { + ifp->mtu6 = ifp->mtu = mtu; + + zlog_info ("interface %s index %d changed %s.", + name, ifi->ifi_index, if_flag_dump(new_flags)); + + if (if_is_operative (ifp)) + { + ifp->flags = new_flags; + if (!if_is_operative (ifp)) + if_down (ifp); else /* Must notify client daemons of new interface status. */ - zebra_interface_up_update (ifp); - } - else - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (if_is_operative (ifp)) - if_up (ifp); - } - } + zebra_interface_up_update (ifp); + } + else + { + ifp->flags = new_flags; + if (if_is_operative (ifp)) + if_up (ifp); + } + } + /* Interface name change */ + else if (strcmp(ifp->name, name) != 0) + { + ifp->mtu = ifp->mtu6 = mtu; + zlog_info("interface index %d was renamed from %s to %s", + ifi->ifi_index, ifp->name, name); + + strncpy(ifp->name, name, INTERFACE_NAMSIZ); + rib_update(); + } + /* Interface mtu change */ + else if (mtu != ifp->mtu) + { + zlog_info("interface index %d mtu changed from %u to %u", + ifp->mtu, mtu); + ifp->mtu = ifp->mtu6 = mtu; + if (if_is_operative (ifp)) + zebra_interface_up_update (ifp); + } } else { - /* RTM_DELLINK. */ - ifp = if_lookup_by_name (name); - + // RTM_DELLINK. + ifp = if_lookup_by_index (ifi->ifi_index); if (ifp == NULL) { - zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find", - name); + zlog (NULL, LOG_WARNING, "interface %s index %d is deleted but can't find", + name, ifi->ifi_index); return 0; } + else + zlog_info ("interface %s index %d deleted.", + name, ifi->ifi_index); if_delete_update (ifp); + if_delete (ifp); } - return 0; } @@ -1188,11 +1246,6 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) /* Request an acknowledgement by setting NLM_F_ACK */ n->nlmsg_flags |= NLM_F_ACK; - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("netlink_talk: %s type %s(%u), seq=%u", nl->name, - lookup (nlmsg_str, n->nlmsg_type), n->nlmsg_type, - n->nlmsg_seq); - /* Send message to netlink interface. */ if (zserv_privs.change (ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); @@ -1217,15 +1270,11 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) } /* Routing table change via netlink interface. */ -static int -netlink_route (int cmd, int family, void *dest, int length, void *gate, - int index, int zebra_flags, int table) +static void +netlink_delroute (int family, void *dest, int length, void *gate, + int index, int table, int proto) { - int ret; - int bytelen; - struct sockaddr_nl snl; - int discard; - + int bytelen = (family == AF_INET ? 4 : 16); struct { struct nlmsghdr n; @@ -1235,59 +1284,25 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, memset (&req, 0, sizeof req); - bytelen = (family == AF_INET ? 4 : 16); - req.n.nlmsg_len = NLMSG_LENGTH (sizeof (struct rtmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - req.n.nlmsg_type = cmd; + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_DELROUTE; req.r.rtm_family = family; + req.r.rtm_scope = RT_SCOPE_NOWHERE; req.r.rtm_table = table; req.r.rtm_dst_len = length; - req.r.rtm_protocol = RTPROT_ZEBRA; - req.r.rtm_scope = RT_SCOPE_UNIVERSE; - - if ((zebra_flags & ZEBRA_FLAG_BLACKHOLE) - || (zebra_flags & ZEBRA_FLAG_REJECT)) - discard = 1; - else - discard = 0; - - if (cmd == RTM_NEWROUTE) - { - if (discard) - { - if (zebra_flags & ZEBRA_FLAG_BLACKHOLE) - req.r.rtm_type = RTN_BLACKHOLE; - else if (zebra_flags & ZEBRA_FLAG_REJECT) - req.r.rtm_type = RTN_UNREACHABLE; - else - assert (RTN_BLACKHOLE != RTN_UNREACHABLE); /* false */ - } - else - req.r.rtm_type = RTN_UNICAST; - } if (dest) addattr_l (&req.n, sizeof req, RTA_DST, dest, bytelen); - if (!discard) - { - if (gate) - addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen); - if (index > 0) - addattr32 (&req.n, sizeof req, RTA_OIF, index); - } + if (gate) + addattr_l (&req.n, sizeof req, RTA_GATEWAY, gate, bytelen); - /* Destination netlink address. */ - memset (&snl, 0, sizeof snl); - snl.nl_family = AF_NETLINK; + if (index > 0) + addattr32 (&req.n, sizeof req, RTA_OIF, index); /* Talk to netlink socket. */ - ret = netlink_talk (&req.n, &netlink_cmd); - if (ret < 0) - return -1; - - return 0; + netlink_talk (&req.n, &netlink_cmd); } /* Routing table change via netlink interface. */ @@ -1326,6 +1341,20 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, else discard = 0; + switch (rib->type) { + case ZEBRA_ROUTE_KERNEL: + /* FIXME: should remember original protocol from RTM_NEWLINK */ + req.r.rtm_protocol = RTPROT_BOOT; + break; + case ZEBRA_ROUTE_CONNECT: + req.r.rtm_protocol = RTPROT_KERNEL; + break; + default: + req.r.rtm_protocol = RTPROT_ZEBRA; + } + + req.r.rtm_scope = rib->scope; + if (cmd == RTM_NEWROUTE) { if (discard) @@ -1343,8 +1372,8 @@ netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, addattr_l (&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); - /* Metric. */ - addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric); + if (rib->type != ZEBRA_ROUTE_CONNECT) + addattr32 (&req.n, sizeof req, RTA_PRIORITY, rib->metric); if (discard) { @@ -1743,12 +1772,12 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) } /* Delete IPv6 route from the kernel. */ -int +void kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table) + unsigned int index, int table) { - return netlink_route (RTM_DELROUTE, AF_INET6, &dest->prefix, - dest->prefixlen, gate, index, flags, table); + netlink_delroute (AF_INET6, &dest->prefix, + dest->prefixlen, gate, index, table, RTPROT_ZEBRA); } #endif /* HAVE_IPV6 */ @@ -1831,72 +1860,20 @@ kernel_read (struct thread *thread) return 0; } -<<<<<<< HEAD:zebra/rt_netlink.c -/* Filter out messages from self that occur on listener socket */ -static void netlink_install_filter (int sock) -======= /* Filter out messages from self that occur on listener socket, caused by our actions on the command socket */ static void netlink_install_filter (int sock, __u32 pid) ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/rt_netlink.c { -<<<<<<< HEAD:zebra/rt_netlink.c - /* - * Filter is equivalent to netlink_route_change - * - * if (h->nlmsg_type == RTM_DELROUTE || h->nlmsg_type == RTM_NEWROUTE) { - * if (rtm->rtm_type != RTM_UNICAST) - * return 0; - * if (rtm->rtm_flags & RTM_F_CLONED) - * return 0; - * if (rtm->rtm_protocol == RTPROT_REDIRECT) - * return 0; - * if (rtm->rtm_protocol == RTPROT_KERNEL) - * return 0; - * if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) - * return 0; - * } - * return 0xffff; - */ -======= ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/rt_netlink.c struct sock_filter filter[] = { -<<<<<<< HEAD:zebra/rt_netlink.c - /* 0*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 1, 0), - /* 2*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 11), - /* 3*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_type)), - /* 4*/ BPF_JUMP(BPF_JMP|BPF_B, RTN_UNICAST, 0, 8), - /* 5*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_flags)), - /* 6*/ BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, RTM_F_CLONED, 6, 0), - /* 7*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_protocol)), - /* 8*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_REDIRECT, 4, 0), - /* 9*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_KERNEL, 0, 1), - /*10*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_ZEBRA, 0, 3), - /*11*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /*12*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 1), - /*13*/ BPF_STMT(BPF_RET|BPF_K, 0), /* drop */ - /*14*/ BPF_STMT(BPF_RET|BPF_K, 0xffff), /* keep */ -======= - /* 0: ldh [4] */ - BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1: jeq 0x18 jt 3 jf 6 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0), - /* 2: jeq 0x19 jt 3 jf 6 */ - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3), - /* 3: ldw [12] */ + /* 0: ldw [12] */ BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), - /* 4: jeq XX jt 5 jf 6 */ + /* 1: jeq XX jt 2 jf 3 */ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), - /* 5: ret 0 (skip) */ + /* 2: ret 0 (skip) */ BPF_STMT(BPF_RET|BPF_K, 0), - /* 6: ret 0xffff (keep) */ + /* 3: ret 0xffff (keep) */ BPF_STMT(BPF_RET|BPF_K, 0xffff), ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/rt_netlink.c }; struct sock_fprog prog = { @@ -1925,9 +1902,6 @@ kernel_init (void) /* Register kernel socket. */ if (netlink.sock > 0) { -<<<<<<< HEAD:zebra/rt_netlink.c - netlink_install_filter (netlink.sock); -======= /* Only want non-blocking on the netlink event socket */ if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, @@ -1938,7 +1912,6 @@ kernel_init (void) netlink_recvbuf (&netlink, nl_rcvbufsize); netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/rt_netlink.c thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } } diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 1b8ded7e..9bbecb95 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -509,13 +509,13 @@ kernel_delete_ipv6 (struct prefix *p, struct rib *rib) /* Delete IPv6 route from the kernel. */ int kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, - unsigned int index, int flags, int table) + unsigned int index, int table) { int route; if (zserv_privs.change(ZPRIVS_RAISE)) zlog (NULL, LOG_ERR, "Can't raise privileges"); - route = kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags); + route = kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index); if (zserv_privs.change(ZPRIVS_LOWER)) zlog (NULL, LOG_ERR, "Can't lower privileges"); diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 4bdb83d5..86956ed7 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -84,17 +84,16 @@ struct rtadv *rtadv = NULL; static struct rtadv * rtadv_new (void) { - struct rtadv *new; - new = XMALLOC (MTYPE_TMP, sizeof (struct rtadv)); - memset (new, 0, sizeof (struct rtadv)); - return new; + return XCALLOC (MTYPE_TMP, sizeof (struct rtadv)); } +#if 0 static void rtadv_free (struct rtadv *rtadv) { XFREE (MTYPE_TMP, rtadv); } +#endif static int rtadv_recv_packet (int sock, u_char *buf, int buflen, @@ -451,7 +450,7 @@ rtadv_read (struct thread *thread) int len; u_char buf[RTADV_MSG_SIZE]; struct sockaddr_in6 from; - unsigned int ifindex; + unsigned int ifindex = 0; int hoplimit = -1; sock = THREAD_FD (thread); @@ -529,12 +528,7 @@ rtadv_make_socket (void) static struct rtadv_prefix * rtadv_prefix_new () { - struct rtadv_prefix *new; - - new = XMALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix)); - memset (new, 0, sizeof (struct rtadv_prefix)); - - return new; + return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix)); } static void diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 658bc5ff..abd1c6fc 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -23,10 +23,7 @@ #ifndef _ZEBRA_RTADV_H #define _ZEBRA_RTADV_H -<<<<<<< HEAD:zebra/rtadv.h -======= #include "vty.h" ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/rtadv.h #include "zebra/interface.h" /* Router advertisement prefix. */ diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index 0b255a53..44715d94 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -21,11 +21,9 @@ */ #include <zebra.h> +extern void netlink_route_read (void); -/* Extern from rt_netlink.c */ -void netlink_route_read (); - -void route_read () +void route_read (void) { netlink_route_read (); } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 1cb9856a..69249779 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -44,6 +44,9 @@ /* Default rtm_table for all clients */ extern struct zebra_t zebrad; +/* Should kernel routes be removed on link down? */ +int rib_system_routes = 0; + /* Hold time for RIB process, should be very minimal. * it is useful to able to set it otherwise for testing, hence exported * as global here for test-rig code. @@ -93,6 +96,7 @@ vrf_alloc (const char *name) return vrf; } +#if 0 /* Free VRF. */ static void vrf_free (struct vrf *vrf) @@ -101,6 +105,7 @@ vrf_free (struct vrf *vrf) XFREE (MTYPE_VRF_NAME, vrf->name); XFREE (MTYPE_VRF, vrf); } +#endif /* Lookup VRF by identifier. */ struct vrf * @@ -109,6 +114,7 @@ vrf_lookup (u_int32_t id) return vector_lookup (vrf_vector, id); } +#if 0 /* Lookup VRF by name. */ static struct vrf * vrf_lookup_by_name (char *name) @@ -122,6 +128,7 @@ vrf_lookup_by_name (char *name) return vrf; return NULL; } +#endif /* Initialize VRF. */ static void @@ -205,14 +212,16 @@ nexthop_free (struct nexthop *nexthop) } struct nexthop * -nexthop_ifindex_add (struct rib *rib, unsigned int ifindex) +nexthop_ifindex_add (struct rib *rib, unsigned int ifindex, + struct in_addr *src) { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IFINDEX; nexthop->ifindex = ifindex; + if (src) + nexthop->src.ipv4 = *src; nexthop_add (rib, nexthop); @@ -224,8 +233,7 @@ nexthop_ifname_add (struct rib *rib, char *ifname) { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IFNAME; nexthop->ifname = XSTRDUP (0, ifname); @@ -239,8 +247,7 @@ nexthop_ipv4_add (struct rib *rib, struct in_addr *ipv4, struct in_addr *src) { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV4; nexthop->gate.ipv4 = *ipv4; if (src) @@ -257,8 +264,7 @@ nexthop_ipv4_ifindex_add (struct rib *rib, struct in_addr *ipv4, { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX; nexthop->gate.ipv4 = *ipv4; if (src) @@ -276,8 +282,7 @@ nexthop_ipv6_add (struct rib *rib, struct in6_addr *ipv6) { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV6; nexthop->gate.ipv6 = *ipv6; @@ -292,8 +297,7 @@ nexthop_ipv6_ifname_add (struct rib *rib, struct in6_addr *ipv6, { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV6_IFNAME; nexthop->gate.ipv6 = *ipv6; nexthop->ifname = XSTRDUP (0, ifname); @@ -309,8 +313,7 @@ nexthop_ipv6_ifindex_add (struct rib *rib, struct in6_addr *ipv6, { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; nexthop->gate.ipv6 = *ipv6; nexthop->ifindex = ifindex; @@ -326,8 +329,7 @@ nexthop_blackhole_add (struct rib *rib) { struct nexthop *nexthop; - nexthop = XMALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); - memset (nexthop, 0, sizeof (struct nexthop)); + nexthop = XCALLOC (MTYPE_NEXTHOP, sizeof (struct nexthop)); nexthop->type = NEXTHOP_TYPE_BLACKHOLE; SET_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE); @@ -336,6 +338,35 @@ nexthop_blackhole_add (struct rib *rib) return nexthop; } +static int +nexthop_isactive(const struct nexthop *nexthop) +{ + struct interface *ifp; + + switch(nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV6: + if (nexthop->ifindex == 0) + return 0; + /* fall through */ + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: + ifp = if_lookup_by_index (nexthop->ifindex); + return (ifp && if_is_operative (ifp)); + + case NEXTHOP_TYPE_IFNAME: + case NEXTHOP_TYPE_IPV4_IFNAME: + case NEXTHOP_TYPE_IPV6_IFNAME: + ifp = if_lookup_by_name(nexthop->ifname); + return (ifp && if_is_operative (ifp)); + + default: + return 1; + } +} + /* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */ static int @@ -348,11 +379,12 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, struct rib *match; struct nexthop *newhop; - if (nexthop->type == NEXTHOP_TYPE_IPV4) - nexthop->ifindex = 0; - if (set) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + { + UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + if (nexthop->type == NEXTHOP_TYPE_IPV4) + nexthop->ifindex = 0; + } /* Make lookup prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); @@ -400,16 +432,32 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, { /* Directly point connected route. */ newhop = match->nexthop; - if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4) - nexthop->ifindex = newhop->ifindex; - - return 1; + if (!newhop) + return 0; /* dead route */ + + if (nexthop_isactive (newhop)) + { + if (set) + { + if (nexthop->type == NEXTHOP_TYPE_IPV4) + nexthop->ifindex = newhop->ifindex; + } + else + { + if (nexthop->ifindex != newhop->ifindex || + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + } + return 1; + } } - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) + else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) + || match->type == ZEBRA_ROUTE_STATIC) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) - && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) + && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE) + && nexthop_isactive (newhop)) { if (set) { @@ -422,7 +470,13 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, || newhop->type == NEXTHOP_TYPE_IFNAME || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) nexthop->rifindex = newhop->ifindex; + if (nexthop->type == NEXTHOP_TYPE_IPV4) + nexthop->ifindex = newhop->ifindex; } + else if (! CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) + || newhop->ifindex != nexthop->ifindex + || nexthop->gate.ipv4.s_addr != newhop->gate.ipv4.s_addr) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); return 1; } return 0; @@ -501,17 +555,36 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, { /* Directly point connected route. */ newhop = match->nexthop; + if (!newhop) + return 0; /* dead route */ - if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6) + /* recursive route, remember index */ + if (nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = newhop->ifindex; - return 1; + if (nexthop_isactive (newhop)) + { + if (set) + { + if (nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; + } + else + { + if (nexthop->ifindex != newhop->ifindex || + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + } + return 1; + } } - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) + else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) || + match->type == ZEBRA_ROUTE_STATIC) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) - && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) + && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE) + && nexthop_isactive (newhop)) { if (set) { @@ -526,7 +599,15 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME) nexthop->rifindex = newhop->ifindex; + if (nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; } + else if (! CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) + || newhop->ifindex != nexthop->ifindex + || !IPV6_ADDR_SAME(&nexthop->gate.ipv6, + &newhop->gate.ipv6)) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + return 1; } return 0; @@ -683,21 +764,12 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) /* Find out if a "selected" RR for the discovered RIB entry exists ever. */ for (match = rn->info; match; match = match->next) -<<<<<<< HEAD:zebra/zebra_rib.c - { - if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } -======= { if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) continue; if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) break; } ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c /* None such found :( */ if (!match) @@ -709,24 +781,24 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) /* Ok, we have a cood candidate, let's check it's nexthop list... */ for (nexthop = match->nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) - { - /* We are happy with either direct or recursive hexthop */ - if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr || - nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr) - return ZEBRA_RIB_FOUND_EXACT; - else { - if (IS_ZEBRA_DEBUG_RIB) - { - char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; - inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); - inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN); - inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN); - zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf); - } - return ZEBRA_RIB_FOUND_NOGATE; + /* We are happy with either direct or recursive hexthop */ + if (nexthop->gate.ipv4.s_addr == qgate->sin.sin_addr.s_addr || + nexthop->rgate.ipv4.s_addr == qgate->sin.sin_addr.s_addr) + return ZEBRA_RIB_FOUND_EXACT; + else + { + if (IS_ZEBRA_DEBUG_RIB) + { + char gate_buf[INET_ADDRSTRLEN], rgate_buf[INET_ADDRSTRLEN], qgate_buf[INET_ADDRSTRLEN]; + inet_ntop (AF_INET, &nexthop->gate.ipv4.s_addr, gate_buf, INET_ADDRSTRLEN); + inet_ntop (AF_INET, &nexthop->rgate.ipv4.s_addr, rgate_buf, INET_ADDRSTRLEN); + inet_ntop (AF_INET, &qgate->sin.sin_addr.s_addr, qgate_buf, INET_ADDRSTRLEN); + zlog_debug ("%s: qgate == %s, gate == %s, rgate == %s", __func__, qgate_buf, gate_buf, rgate_buf); + } + return ZEBRA_RIB_FOUND_NOGATE; + } } - } return ZEBRA_RIB_NOTFOUND; } @@ -795,8 +867,10 @@ rib_match_ipv6 (struct in6_addr *addr) } #endif /* HAVE_IPV6 */ -#define RIB_SYSTEM_ROUTE(R) \ +#define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) +#define RIB_SHOULD_UPDATE(R) \ + (! CHECK_FLAG((R)->status, RIB_ENTRY_PRESERVE) ) /* This function verifies reachability of one given nexthop, which can be * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored @@ -807,7 +881,6 @@ rib_match_ipv6 (struct in6_addr *addr) * * The return value is the final value of 'ACTIVE' flag. */ - static int nexthop_active_check (struct route_node *rn, struct rib *rib, struct nexthop *nexthop, int set) @@ -980,8 +1053,6 @@ rib_uninstall_kernel (struct route_node *rn, struct rib *rib) break; #ifdef HAVE_IPV6 case AF_INET6: - if (IS_ZEBRA_DEBUG_RIB) - zlog_debug ("%s: calling kernel_delete_ipv4 (%p, %p)", __func__, rn, rib); ret = kernel_delete_ipv6 (&rn->p, rib); break; #endif /* HAVE_IPV6 */ @@ -1000,7 +1071,7 @@ rib_uninstall (struct route_node *rn, struct rib *rib) if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) { redistribute_delete (&rn->p, rib); - if (! RIB_SYSTEM_ROUTE (rib)) + if (RIB_SHOULD_UPDATE (rib)) rib_uninstall_kernel (rn, rib); UNSET_FLAG (rib->flags, ZEBRA_FLAG_SELECTED); } @@ -1125,17 +1196,17 @@ rib_process (struct route_node *rn) if (CHECK_FLAG (select->flags, ZEBRA_FLAG_CHANGED)) { redistribute_delete (&rn->p, select); - if (! RIB_SYSTEM_ROUTE (select)) + if (RIB_SHOULD_UPDATE (select)) rib_uninstall_kernel (rn, select); /* Set real nexthop. */ nexthop_active_update (rn, select, 1); - if (! RIB_SYSTEM_ROUTE (select)) + if (RIB_SHOULD_UPDATE (select)) rib_install_kernel (rn, select); redistribute_add (&rn->p, select); } - else if (! RIB_SYSTEM_ROUTE (select)) + else if (RIB_SHOULD_UPDATE (select)) { /* Housekeeping code to deal with race conditions in kernel with linux @@ -1166,7 +1237,7 @@ rib_process (struct route_node *rn) zlog_debug ("%s: %s/%d: Removing existing route, fib %p", __func__, buf, rn->p.prefixlen, fib); redistribute_delete (&rn->p, fib); - if (! RIB_SYSTEM_ROUTE (fib)) + if (RIB_SHOULD_UPDATE (fib)) rib_uninstall_kernel (rn, fib); UNSET_FLAG (fib->flags, ZEBRA_FLAG_SELECTED); @@ -1186,7 +1257,7 @@ rib_process (struct route_node *rn) /* Set real nexthop. */ nexthop_active_update (rn, select, 1); - if (! RIB_SYSTEM_ROUTE (select)) + if (RIB_SHOULD_UPDATE (select)) rib_install_kernel (rn, select); SET_FLAG (select->flags, ZEBRA_FLAG_SELECTED); redistribute_add (&rn->p, select); @@ -1200,129 +1271,31 @@ rib_process (struct route_node *rn) rn->p.prefixlen, del, rn); rib_unlink (rn, del); } -<<<<<<< HEAD:zebra/zebra_rib.c end: if (IS_ZEBRA_DEBUG_RIB_Q) zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn); } -/* Take a list of route_node structs and return 1, if there was a record picked from - * it and processed by rib_process(). Don't process more, than one RN record; operate - * only in the specified sub-queue. - */ -unsigned int -process_subq (struct list * subq, u_char qindex) -{ - struct listnode *lnode; - struct route_node *rnode; - if (!(lnode = listhead (subq))) - return 0; - rnode = listgetdata (lnode); - rib_process (rnode); - if (rnode->info) /* The first RIB record is holding the flags bitmask. */ - UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); - route_unlock_node (rnode); - list_delete_node (subq, lnode); - return 1; -} - -/* Dispatch the meta queue by picking, processing and unlocking the next RN from - * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and data - * is pointed to the meta queue structure. - */ -static wq_item_status -meta_queue_process (struct work_queue *dummy, void *data) -{ - struct meta_queue * mq = data; - u_char i; - for (i = 0; i < MQ_SIZE; i++) - if (process_subq (mq->subq[i], i)) - { - mq->size--; - break; - } - return mq->size ? WQ_REQUEUE : WQ_SUCCESS; -} -======= ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c - -<<<<<<< HEAD:zebra/zebra_rib.c -/* Look into the RN and queue it into one or more priority queues, increasing the size - * for each data push done. - */ -void rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) -{ - u_char qindex; - struct rib *rib; - char buf[INET6_ADDRSTRLEN]; -======= -end: ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c - if (IS_ZEBRA_DEBUG_RIB_Q) -<<<<<<< HEAD:zebra/zebra_rib.c - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - for (rib = rn->info; rib; rib = rib->next) - { - switch (rib->type) - { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - qindex = 0; - break; - case ZEBRA_ROUTE_STATIC: - qindex = 1; - break; - case ZEBRA_ROUTE_RIP: - case ZEBRA_ROUTE_RIPNG: - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - case ZEBRA_ROUTE_ISIS: - qindex = 2; - break; - case ZEBRA_ROUTE_BGP: - qindex = 3; - break; - default: - qindex = 4; - break; - } - /* Invariant: at this point we always have rn->info set. */ - if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex))) - { - if (IS_ZEBRA_DEBUG_RIB_Q) - zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex); - continue; - } - SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); - listnode_add (mq->subq[qindex], rn); - route_lock_node (rn); - mq->size++; - if (IS_ZEBRA_DEBUG_RIB_Q) - zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex); - } -======= - zlog_debug ("%s: %s/%d: rn %p dequeued", __func__, buf, rn->p.prefixlen, rn); ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c -} - -<<<<<<< HEAD:zebra/zebra_rib.c -======= -/* Take a list of route_node structs and return 1, if there was a record picked from - * it and processed by rib_process(). Don't process more, than one RN record; operate - * only in the specified sub-queue. +/* Take a list of route_node structs and return 1, if there was a record + * picked from it and processed by rib_process(). Don't process more, + * than one RN record; operate only in the specified sub-queue. */ static unsigned int process_subq (struct list * subq, u_char qindex) { - struct listnode *lnode; + struct listnode *lnode = listhead (subq); struct route_node *rnode; - if (!(lnode = listhead (subq))) + + if (!lnode) return 0; + rnode = listgetdata (lnode); rib_process (rnode); + if (rnode->info) /* The first RIB record is holding the flags bitmask. */ UNSET_FLAG (((struct rib *)rnode->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); + route_unlock_node (rnode); list_delete_node (subq, lnode); return 1; @@ -1336,69 +1309,68 @@ static wq_item_status meta_queue_process (struct work_queue *dummy, void *data) { struct meta_queue * mq = data; - u_char i; + unsigned i; + for (i = 0; i < MQ_SIZE; i++) if (process_subq (mq->subq[i], i)) - { - mq->size--; - break; - } + { + mq->size--; + break; + } return mq->size ? WQ_REQUEUE : WQ_SUCCESS; } -/* Look into the RN and queue it into one or more priority queues, increasing the size - * for each data push done. +/* Map from rib types to queue type (priority) in meta queue */ +static const u_char meta_queue_map[ZEBRA_ROUTE_MAX] = { + [ZEBRA_ROUTE_SYSTEM] = 4, + [ZEBRA_ROUTE_KERNEL] = 0, + [ZEBRA_ROUTE_CONNECT] = 0, + [ZEBRA_ROUTE_STATIC] = 1, + [ZEBRA_ROUTE_RIP] = 2, + [ZEBRA_ROUTE_RIPNG] = 2, + [ZEBRA_ROUTE_OSPF] = 2, + [ZEBRA_ROUTE_OSPF6] = 2, + [ZEBRA_ROUTE_ISIS] = 2, + [ZEBRA_ROUTE_BGP] = 3, + [ZEBRA_ROUTE_HSLS] = 4, +}; + +/* Look into the RN and queue it into one or more priority queues, + * increasing the size for each data push done. */ static void rib_meta_queue_add (struct meta_queue *mq, struct route_node *rn) { - u_char qindex; struct rib *rib; char buf[INET6_ADDRSTRLEN]; + if (IS_ZEBRA_DEBUG_RIB_Q) inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); + for (rib = rn->info; rib; rib = rib->next) - { - switch (rib->type) - { - case ZEBRA_ROUTE_KERNEL: - case ZEBRA_ROUTE_CONNECT: - qindex = 0; - break; - case ZEBRA_ROUTE_STATIC: - qindex = 1; - break; - case ZEBRA_ROUTE_RIP: - case ZEBRA_ROUTE_RIPNG: - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - case ZEBRA_ROUTE_ISIS: - qindex = 2; - break; - case ZEBRA_ROUTE_BGP: - qindex = 3; - break; - default: - qindex = 4; - break; - } - /* Invariant: at this point we always have rn->info set. */ - if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex))) { + u_char qindex = meta_queue_map[rib->type]; + + /* Invariant: at this point we always have rn->info set. */ + if (CHECK_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex))) + { + if (IS_ZEBRA_DEBUG_RIB_Q) + zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", + __func__, buf, rn->p.prefixlen, rn, qindex); + continue; + } + + SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); + listnode_add (mq->subq[qindex], rn); + route_lock_node (rn); + mq->size++; + if (IS_ZEBRA_DEBUG_RIB_Q) - zlog_debug ("%s: %s/%d: rn %p is already queued in sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex); - continue; - } - SET_FLAG (((struct rib *)rn->info)->rn_status, RIB_ROUTE_QUEUED(qindex)); - listnode_add (mq->subq[qindex], rn); - route_lock_node (rn); - mq->size++; - if (IS_ZEBRA_DEBUG_RIB_Q) - zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u", __func__, buf, rn->p.prefixlen, rn, qindex); - } + zlog_debug ("%s: %s/%d: queued rn %p into sub-queue %u", + __func__, buf, rn->p.prefixlen, rn, qindex); + } } ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c /* Add route_node to work queue and schedule processing */ static void rib_queue_add (struct zebra_t *zebra, struct route_node *rn) @@ -1441,48 +1413,31 @@ rib_queue_add (struct zebra_t *zebra, struct route_node *rn) work_queue_add (zebra->ribq, zebra->mq); rib_meta_queue_add (zebra->mq, rn); -<<<<<<< HEAD:zebra/zebra_rib.c -======= if (IS_ZEBRA_DEBUG_RIB_Q) zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn); ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c -<<<<<<< HEAD:zebra/zebra_rib.c - if (IS_ZEBRA_DEBUG_RIB_Q) - zlog_debug ("%s: %s/%d: rn %p queued", __func__, buf, rn->p.prefixlen, rn); - -======= ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c return; } -/* Create new meta queue. A destructor function doesn't seem to be necessary here. */ -<<<<<<< HEAD:zebra/zebra_rib.c -struct meta_queue * -meta_queue_new () -======= +/* Create new meta queue. + A destructor function doesn't seem to be necessary here. + */ static struct meta_queue * meta_queue_new (void) ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c { struct meta_queue *new; - unsigned i, failed = 0; + unsigned i; + + new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue)); + assert(new); - if ((new = XCALLOC (MTYPE_WORK_QUEUE, sizeof (struct meta_queue))) == NULL) - return NULL; for (i = 0; i < MQ_SIZE; i++) - if ((new->subq[i] = list_new ()) == NULL) - failed = 1; - if (failed) - { - for (i = 0; i < MQ_SIZE; i++) - if (new->subq[i]) - list_delete (new->subq[i]); - XFREE (MTYPE_WORK_QUEUE, new); - return NULL; - } - new->size = 0; + { + new->subq[i] = list_new (); + assert(new->subq[i]); + } + return new; } @@ -1587,8 +1542,6 @@ rib_link (struct route_node *rn, struct rib *rib) static void rib_addnode (struct route_node *rn, struct rib *rib) -<<<<<<< HEAD:zebra/zebra_rib.c -======= { /* RIB node has been un-removed before route-node is processed. * route_node must hence already be on the queue for processing.. @@ -1610,32 +1563,7 @@ rib_addnode (struct route_node *rn, struct rib *rib) static void rib_unlink (struct route_node *rn, struct rib *rib) ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c { -<<<<<<< HEAD:zebra/zebra_rib.c - /* RIB node has been un-removed before route-node is processed. - * route_node must hence already be on the queue for processing.. - */ - if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED)) - { - if (IS_ZEBRA_DEBUG_RIB) - { - char buf[INET6_ADDRSTRLEN]; - inet_ntop (rn->p.family, &rn->p.u.prefix, buf, INET6_ADDRSTRLEN); - zlog_debug ("%s: %s/%d: rn %p, un-removed rib %p", - __func__, buf, rn->p.prefixlen, rn, rib); - } - UNSET_FLAG (rib->status, RIB_ENTRY_REMOVED); - return; - } - rib_link (rn, rib); -} - -static void -rib_unlink (struct route_node *rn, struct rib *rib) -{ -======= ->>>>>>> 41dc3488cf127a1e23333459a0c316ded67f7ff3:zebra/zebra_rib.c struct nexthop *nexthop, *next; char buf[INET6_ADDRSTRLEN]; @@ -1695,7 +1623,7 @@ int rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct in_addr *gate, struct in_addr *src, unsigned int ifindex, u_int32_t vrf_id, - u_int32_t metric, u_char distance) + u_int32_t metric, u_int8_t distance, u_int8_t scope) { struct rib *rib; struct rib *same = NULL; @@ -1703,6 +1631,7 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, struct route_node *rn; struct nexthop *nexthop; + /* Lookup table. */ table = vrf_table (AFI_IP, SAFI_UNICAST, 0); if (! table) @@ -1758,6 +1687,7 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, rib->table = vrf_id; rib->nexthop_num = 0; rib->uptime = time (NULL); + rib->scope = scope; /* Nexthop settings. */ if (gate) @@ -1768,12 +1698,18 @@ rib_add_ipv4 (int type, int flags, struct prefix_ipv4 *p, nexthop_ipv4_add (rib, gate, src); } else - nexthop_ifindex_add (rib, ifindex); + nexthop_ifindex_add (rib, ifindex, src); /* If this route is kernel route, set FIB flag to the route. */ - if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + if (RIB_SYSTEM_ROUTE (rib)) + { + /* Mark system routes with the don't touch me flag */ + if (! rib_system_routes) + SET_FLAG(rib->status, RIB_ENTRY_PRESERVE); + + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + } /* Link new rib to node.*/ if (IS_ZEBRA_DEBUG_RIB) @@ -1806,10 +1742,10 @@ void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen); zlog_debug ( - "%s: refcnt == %lu, uptime == %u, type == %u, table == %d", + "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d", func, rib->refcnt, - rib->uptime, + (unsigned long) rib->uptime, rib->type, rib->table ); @@ -1931,8 +1867,7 @@ void rib_lookup_and_pushup (struct prefix_ipv4 * p) */ for (rib = rn->info; rib; rib = rib->next) { - if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) && - ! RIB_SYSTEM_ROUTE (rib)) + if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED) && RIB_SHOULD_UPDATE (rib)) { changed = 1; if (IS_ZEBRA_DEBUG_RIB) @@ -2350,8 +2285,7 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, static_delete_ipv4 (p, gate, ifname, update->distance, vrf_id); /* Make new static route structure. */ - si = XMALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4)); - memset (si, 0, sizeof (struct static_ipv4)); + si = XCALLOC (MTYPE_STATIC_IPV4, sizeof (struct static_ipv4)); si->type = type; si->distance = distance; @@ -2392,6 +2326,9 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, /* Install into rib. */ static_install_ipv4 (p, si); + /* Scan for possible recursive route changes */ + rib_update(); + return 1; } @@ -2456,6 +2393,9 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, route_unlock_node (rn); + /* Scan for possible recursive route changes */ + rib_update(); + return 1; } @@ -2476,7 +2416,7 @@ rib_bogus_ipv6 (int type, struct prefix_ipv6 *p, if (type == ZEBRA_ROUTE_KERNEL && IN6_IS_ADDR_UNSPECIFIED (&p->prefix) && p->prefixlen == 96 && gate && IN6_IS_ADDR_UNSPECIFIED (gate)) { - kernel_delete_ipv6_old (p, gate, ifindex, 0, table); + kernel_delete_ipv6_old (p, gate, ifindex, table); return 1; } return 0; @@ -2558,12 +2498,18 @@ rib_add_ipv6 (int type, int flags, struct prefix_ipv6 *p, nexthop_ipv6_add (rib, gate); } else - nexthop_ifindex_add (rib, ifindex); + nexthop_ifindex_add (rib, ifindex, NULL); /* If this route is kernel route, set FIB flag to the route. */ if (type == ZEBRA_ROUTE_KERNEL || type == ZEBRA_ROUTE_CONNECT) - for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) - SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + { + /* Mark system routes with the don't touch me flag */ + if (! rib_system_routes) + SET_FLAG(rib->status, RIB_ENTRY_PRESERVE); + + for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) + SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB); + } /* Link new rib to node.*/ rib_addnode (rn, rib); @@ -2894,8 +2840,7 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, } /* Make new static route structure. */ - si = XMALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6)); - memset (si, 0, sizeof (struct static_ipv6)); + si = XCALLOC (MTYPE_STATIC_IPV6, sizeof (struct static_ipv6)); si->type = type; si->distance = distance; @@ -2938,6 +2883,8 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* Install into rib. */ static_install_ipv6 (p, si); + /* Scan for possible recursive route changes */ + rib_update(); return 1; } @@ -2991,6 +2938,7 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, XFREE (0, si->ifname); XFREE (MTYPE_STATIC_IPV6, si); + rib_update(); return 1; } #endif /* HAVE_IPV6 */ @@ -3015,6 +2963,7 @@ rib_update (void) rib_queue_add (&zebrad, rn); } +#if 0 /* Interface goes up. */ static void rib_if_up (struct interface *ifp) @@ -3028,6 +2977,7 @@ rib_if_down (struct interface *ifp) { rib_update (); } +#endif /* Remove all routes which comes from non main table. */ static void @@ -3107,7 +3057,7 @@ rib_close_table (struct route_table *table) for (rn = route_top (table); rn; rn = route_next (rn)) for (rib = rn->info; rib; rib = rib->next) { - if (! RIB_SYSTEM_ROUTE (rib) + if (RIB_SHOULD_UPDATE (rib) && CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED)) rib_uninstall_kernel (rn, rib); } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 0c313921..f50ab05e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2030,10 +2030,10 @@ static int config_write_protocol(struct vty *vty) } /* table node for protocol filtering */ -struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; +static struct cmd_node protocol_node = { PROTOCOL_NODE, "", 1 }; /* IP node for static routes. */ -struct cmd_node ip_node = { IP_NODE, "", 1 }; +static struct cmd_node ip_node = { IP_NODE, "", 1 }; /* Route VTY. */ void diff --git a/zebra/zserv.c b/zebra/zserv.c index ef79eaad..76e74088 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -773,7 +773,7 @@ zread_ipv4_add (struct zserv *client, u_short length) { case ZEBRA_NEXTHOP_IFINDEX: ifindex = stream_getl (s); - nexthop_ifindex_add (rib, ifindex); + nexthop_ifindex_add (rib, ifindex, NULL); break; case ZEBRA_NEXTHOP_IFNAME: ifname_len = stream_getc (s); @@ -1569,7 +1569,7 @@ config_write_table (struct vty *vty) } /* table node for routing tables. */ -struct cmd_node table_node = +static struct cmd_node table_node = { TABLE_NODE, "", /* This node has no interface. */ @@ -1689,7 +1689,7 @@ config_write_forwarding (struct vty *vty) } /* table node for routing tables. */ -struct cmd_node forwarding_node = +static struct cmd_node forwarding_node = { FORWARDING_NODE, "", /* This node has no interface. */ |