]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #3959 from donaldsharp/connected_6.0
authorJafar Al-Gharaibeh <Jafaral@users.noreply.github.com>
Tue, 19 Mar 2019 05:11:37 +0000 (00:11 -0500)
committerGitHub <noreply@github.com>
Tue, 19 Mar 2019 05:11:37 +0000 (00:11 -0500)
Connected 6.0

include/linux/if_addr.h [new file with mode: 0644]
include/subdir.am
lib/if.h
zebra/connected.c
zebra/connected.h
zebra/if_ioctl.c
zebra/if_ioctl_solaris.c
zebra/if_netlink.c
zebra/kernel_socket.c
zebra/zebra_rib.c
zebra/zebra_vty.c

diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
new file mode 100644 (file)
index 0000000..a924606
--- /dev/null
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_IF_ADDR_H
+#define __LINUX_IF_ADDR_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct ifaddrmsg {
+       __u8            ifa_family;
+       __u8            ifa_prefixlen;  /* The prefix length            */
+       __u8            ifa_flags;      /* Flags                        */
+       __u8            ifa_scope;      /* Address scope                */
+       __u32           ifa_index;      /* Link index                   */
+};
+
+/*
+ * Important comment:
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ *
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
+ */
+enum {
+       IFA_UNSPEC,
+       IFA_ADDRESS,
+       IFA_LOCAL,
+       IFA_LABEL,
+       IFA_BROADCAST,
+       IFA_ANYCAST,
+       IFA_CACHEINFO,
+       IFA_MULTICAST,
+       IFA_FLAGS,
+       IFA_RT_PRIORITY,  /* u32, priority/metric for prefix route */
+       __IFA_MAX,
+};
+
+#define IFA_MAX (__IFA_MAX - 1)
+
+/* ifa_flags */
+#define IFA_F_SECONDARY                0x01
+#define IFA_F_TEMPORARY                IFA_F_SECONDARY
+
+#define        IFA_F_NODAD             0x02
+#define IFA_F_OPTIMISTIC       0x04
+#define IFA_F_DADFAILED                0x08
+#define        IFA_F_HOMEADDRESS       0x10
+#define IFA_F_DEPRECATED       0x20
+#define IFA_F_TENTATIVE                0x40
+#define IFA_F_PERMANENT                0x80
+#define IFA_F_MANAGETEMPADDR   0x100
+#define IFA_F_NOPREFIXROUTE    0x200
+#define IFA_F_MCAUTOJOIN       0x400
+#define IFA_F_STABLE_PRIVACY   0x800
+
+struct ifa_cacheinfo {
+       __u32   ifa_prefered;
+       __u32   ifa_valid;
+       __u32   cstamp; /* created timestamp, hundredths of seconds */
+       __u32   tstamp; /* updated timestamp, hundredths of seconds */
+};
+
+/* backwards compatibility for userspace */
+#define IFA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+
+#endif
index 731785d4b4dd61ffdfe802197d8abf8601e5f69e..0d7fed28529e12bcf0f6fe869640363dd974908c 100644 (file)
@@ -1,4 +1,5 @@
 noinst_HEADERS += \
+       include/linux/if_addr.h \
        include/linux/if_bridge.h \
        include/linux/if_link.h \
        include/linux/lwtunnel.h \
index a861cf2d855907d4714a9576e7a22abb64bad5ba..a52023d0546c860972d55847aacb539cfc7aa7d8 100644 (file)
--- a/lib/if.h
+++ b/lib/if.h
@@ -345,6 +345,8 @@ DECLARE_QOBJ_TYPE(interface)
 DECLARE_HOOK(if_add, (struct interface * ifp), (ifp))
 DECLARE_KOOH(if_del, (struct interface * ifp), (ifp))
 
+#define METRIC_MAX (~0)
+
 /* Connected address structure. */
 struct connected {
        /* Attached interface. */
@@ -392,6 +394,13 @@ struct connected {
 
        /* Label for Linux 2.2.X and upper. */
        char *label;
+
+       /*
+        * Used for setting the connected route's cost. If the metric
+        * here is set to METRIC_MAX the connected route falls back to
+        * "struct interface"
+        */
+       uint32_t metric;
 };
 
 /* Nbr Connected address structure. */
index 57bfcc4d16d59bbd6553bd3641f3acfa9a6ecf0d..147715dd16e85a1353c4d67866d2e55353086b59 100644 (file)
@@ -208,6 +208,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
                .ifindex = ifp->ifindex,
                .vrf_id = ifp->vrf_id,
        };
+       uint32_t metric;
 
        if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
                return;
@@ -241,11 +242,13 @@ void connected_up(struct interface *ifp, struct connected *ifc)
                break;
        }
 
+       metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
+                               ifc->metric : ifp->metric;
        rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
-               NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+               NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
 
        rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
-               NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+               NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
                char buf[PREFIX_STRLEN];
@@ -274,7 +277,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
 /* Add connected IPv4 route to the interface. */
 void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
                        uint8_t prefixlen, struct in_addr *broad,
-                       const char *label)
+                       const char *label, uint32_t metric)
 {
        struct prefix_ipv4 *p;
        struct connected *ifc;
@@ -286,6 +289,7 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
        ifc = connected_new();
        ifc->ifp = ifp;
        ifc->flags = flags;
+       ifc->metric = metric;
        /* If we get a notification from the kernel,
         * we can safely assume the address is known to the kernel */
        SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
@@ -496,7 +500,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
 /* Add connected IPv6 route to the interface. */
 void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
                        struct in6_addr *broad, uint8_t prefixlen,
-                       const char *label)
+                       const char *label, uint32_t metric)
 {
        struct prefix_ipv6 *p;
        struct connected *ifc;
@@ -508,6 +512,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
        ifc = connected_new();
        ifc->ifp = ifp;
        ifc->flags = flags;
+       ifc->metric = metric;
        /* If we get a notification from the kernel,
         * we can safely assume the address is known to the kernel */
        SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
index 75b6e05bda714878a175eace7140ef4665a7dc20..d9c41b328b2d17207edbcf7aa3713390d1f0c386 100644 (file)
@@ -36,7 +36,8 @@ extern struct connected *connected_check_ptp(struct interface *ifp,
 
 extern void connected_add_ipv4(struct interface *ifp, int flags,
                               struct in_addr *addr, uint8_t prefixlen,
-                              struct in_addr *broad, const char *label);
+                              struct in_addr *broad, const char *label,
+                              uint32_t metric);
 
 extern void connected_delete_ipv4(struct interface *ifp, int flags,
                                  struct in_addr *addr, uint8_t prefixlen,
@@ -49,7 +50,8 @@ extern void connected_down(struct interface *ifp, struct connected *ifc);
 
 extern void connected_add_ipv6(struct interface *ifp, int flags,
                               struct in6_addr *address, struct in6_addr *broad,
-                              uint8_t prefixlen, const char *label);
+                              uint8_t prefixlen, const char *label,
+                              uint32_t metric);
 extern void connected_delete_ipv6(struct interface *ifp,
                                  struct in6_addr *address,
                                  struct in6_addr *broad, uint8_t prefixlen);
index 176bb2bbad591dda7fba121f171861af7cb29b46..d7c64865841767cf2657ef600d2bf6b4ebe1a3dc 100644 (file)
@@ -233,7 +233,8 @@ static int if_getaddrs(void)
                        }
 
                        connected_add_ipv4(ifp, flags, &addr->sin_addr,
-                                          prefixlen, dest_pnt, NULL);
+                                          prefixlen, dest_pnt, NULL,
+                                          METRIC_MAX);
                }
                if (ifap->ifa_addr->sa_family == AF_INET6) {
                        struct sockaddr_in6 *addr;
@@ -255,7 +256,7 @@ static int if_getaddrs(void)
 #endif
 
                        connected_add_ipv6(ifp, flags, &addr->sin6_addr, NULL,
-                                          prefixlen, NULL);
+                                          prefixlen, NULL, METRIC_MAX);
                }
        }
 
index 5a58fe1751cbc54bbbb131aaf1ccc4007db85284..20668183bbfdf656529f62d5be3ef83a0410256e 100644 (file)
@@ -298,10 +298,11 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr,
        /* Set address to the interface. */
        if (af == AF_INET)
                connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen,
-                                  (struct in_addr *)dest_pnt, label);
+                                  (struct in_addr *)dest_pnt, label,
+                                  METRIC_MAX);
        else if (af == AF_INET6)
                connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL,
-                                  prefixlen, label);
+                                  prefixlen, label, METRIC_MAX);
 
        return 0;
 }
index a15d914243df9b27ca522edccaf77dc6dfe22c89..bed6fbf3d84b1f89853d747165f7c397f3ec9036 100644 (file)
@@ -889,6 +889,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        uint8_t flags = 0;
        char *label = NULL;
        struct zebra_ns *zns;
+       uint32_t metric = METRIC_MAX;
 
        zns = zebra_ns_lookup(ns_id);
        ifa = NLMSG_DATA(h);
@@ -996,6 +997,9 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        if (label && strcmp(ifp->name, label) == 0)
                label = NULL;
 
+       if (tb[IFA_RT_PRIORITY])
+               metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]);
+
        /* Register interface address to the interface. */
        if (ifa->ifa_family == AF_INET) {
                if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
@@ -1007,7 +1011,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                if (h->nlmsg_type == RTM_NEWADDR)
                        connected_add_ipv4(ifp, flags, (struct in_addr *)addr,
                                           ifa->ifa_prefixlen,
-                                          (struct in_addr *)broad, label);
+                                          (struct in_addr *)broad, label,
+                                          metric);
                else
                        connected_delete_ipv4(
                                ifp, flags, (struct in_addr *)addr,
@@ -1032,7 +1037,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                                connected_add_ipv6(ifp, flags,
                                                   (struct in6_addr *)addr,
                                                   (struct in6_addr *)broad,
-                                                  ifa->ifa_prefixlen, label);
+                                                  ifa->ifa_prefixlen, label,
+                                                  metric);
                } else
                        connected_delete_ipv6(ifp, (struct in6_addr *)addr,
                                              (struct in6_addr *)broad,
index ff035fb3536226c0a415177a07766d6135f9b776..3721ed52a3ea7ab5c93b85a42b65ce83252ed375 100644 (file)
@@ -759,7 +759,8 @@ int ifam_read(struct ifa_msghdr *ifam)
                        connected_add_ipv4(ifp, flags, &addr.sin.sin_addr,
                                           ip_masklen(mask.sin.sin_addr),
                                           &brd.sin.sin_addr,
-                                          (isalias ? ifname : NULL));
+                                          (isalias ? ifname : NULL),
+                                          METRIC_MAX);
                else
                        connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr,
                                              ip_masklen(mask.sin.sin_addr),
@@ -776,7 +777,8 @@ int ifam_read(struct ifa_msghdr *ifam)
                        connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
                                           NULL,
                                           ip6_masklen(mask.sin6.sin6_addr),
-                                          (isalias ? ifname : NULL));
+                                          (isalias ? ifname : NULL),
+                                          METRIC_MAX);
                else
                        connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL,
                                              ip6_masklen(mask.sin6.sin6_addr));
index ab07549ec26d13054dde6d5368ebdb2db3a02e74..9e56559522c7ff07be74b7b9fb1ec77586ebad68 100644 (file)
@@ -1409,7 +1409,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                                 * from ourselves we don't
                                 * over write this pointer
                                 */
-                               dest->selected_fib = NULL;
+                               dest->selected_fib = new;
                        }
                        /* If install succeeded or system route, cleanup flags
                         * for prior route. */
index f787d641b4428ba46b3d8e90038df53488d5c602..ffd84825513486a746638326310e44add1f3248c 100644 (file)
@@ -374,6 +374,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
        json_object *json_labels = NULL;
        time_t uptime;
        struct tm *tm;
+       rib_dest_t *dest = rib_dest_from_rnode(rn);
 
        uptime = time(NULL);
        uptime -= re->uptime;
@@ -398,11 +399,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
                        json_object_boolean_true_add(json_route, "selected");
 
-               if (re->type != ZEBRA_ROUTE_CONNECT) {
-                       json_object_int_add(json_route, "distance",
-                                           re->distance);
-                       json_object_int_add(json_route, "metric", re->metric);
-               }
+               if (dest->selected_fib == re)
+                       json_object_boolean_true_add(json_route,
+                                                    "destSelected");
+
+               json_object_int_add(json_route, "distance",
+                                   re->distance);
+               json_object_int_add(json_route, "metric", re->metric);
 
                if (re->tag)
                        json_object_int_add(json_route, "tag", re->tag);
@@ -611,7 +614,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
                                srcdest_rnode2str(rn, buf, sizeof buf));
 
                        /* Distance and metric display. */
-                       if (re->type != ZEBRA_ROUTE_CONNECT)
+                       if (((re->type == ZEBRA_ROUTE_CONNECT) &&
+                            (re->distance || re->metric)) ||
+                           (re->type != ZEBRA_ROUTE_CONNECT))
                                len += vty_out(vty, " [%u/%u]", re->distance,
                                               re->metric);
                } else {
@@ -741,15 +746,14 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
        char buf[BUFSIZ];
 
        json = json_object_new_object();
+       json_prefix = json_object_new_array();
 
        RNODE_FOREACH_RE (rn, re) {
-               json_prefix = json_object_new_array();
                vty_show_ip_route(vty, rn, re, json_prefix);
-               prefix2str(&rn->p, buf, sizeof buf);
-               json_object_object_add(json, buf, json_prefix);
-               json_prefix = NULL;
        }
 
+       prefix2str(&rn->p, buf, sizeof(buf));
+       json_object_object_add(json, buf, json_prefix);
        vty_out(vty, "%s\n", json_object_to_json_string_ext(
                                             json, JSON_C_TO_STRING_PRETTY));
        json_object_free(json);