]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/kernel_socket.c
zebra: Prevent installation of connected multiple times
[mirror_frr.git] / zebra / kernel_socket.c
index 5ff66f7c63371a8aa9c73d0999e633cef44e610c..ce1f17111bf46b7507e3906d22a5820d28ddd82f 100644 (file)
@@ -1011,6 +1011,8 @@ void rtm_read(struct rt_msghdr *rtm)
        ifindex_t ifindex = 0;
        afi_t afi;
        char fbuf[64];
+       int32_t proto = ZEBRA_ROUTE_KERNEL;
+       uint8_t distance = 0;
 
        zebra_flags = 0;
 
@@ -1042,8 +1044,11 @@ void rtm_read(struct rt_msghdr *rtm)
        if (!(flags & RTF_GATEWAY))
                return;
 
-       if (flags & RTF_PROTO1)
+       if (flags & RTF_PROTO1) {
                SET_FLAG(zebra_flags, ZEBRA_FLAG_SELFROUTE);
+               proto = ZEBRA_ROUTE_STATIC;
+               distance = 255;
+       }
 
        memset(&nh, 0, sizeof(nh));
 
@@ -1111,13 +1116,13 @@ void rtm_read(struct rt_msghdr *rtm)
                           0, true);
        if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
            || rtm->rtm_type == RTM_CHANGE)
-               rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL, 0,
-                       zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN,
-                       0, 0, 0, 0);
+               rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags,
+                       &p, NULL, &nh, 0, RT_TABLE_MAIN, 0, 0, distance, 0,
+                       false);
        else
-               rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
-                          0, zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0,
-                          0, true);
+               rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0,
+                          zebra_flags, &p, NULL, &nh, 0, RT_TABLE_MAIN, 0,
+                          distance, true);
 }
 
 /* Interface function for the kernel routing table updates.  Support
@@ -1292,7 +1297,7 @@ static void rtmsg_debug(struct rt_msghdr *rtm)
 #endif /* RTAX_MAX */
 
 /* Kernel routing table and interface updates via routing socket. */
-static int kernel_read(struct thread *thread)
+static void kernel_read(struct thread *thread)
 {
        int sock;
        int nbytes;
@@ -1356,11 +1361,11 @@ static int kernel_read(struct thread *thread)
                if (errno != EAGAIN && errno != EWOULDBLOCK)
                        flog_err_sys(EC_LIB_SOCKET, "routing socket error: %s",
                                     safe_strerror(errno));
-               return 0;
+               return;
        }
 
        if (nbytes == 0)
-               return 0;
+               return;
 
        thread_add_read(zrouter.master, kernel_read, NULL, sock, NULL);
 
@@ -1377,7 +1382,7 @@ static int kernel_read(struct thread *thread)
                zlog_debug(
                        "kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d",
                        rtm->rtm_msglen, nbytes, rtm->rtm_type);
-               return -1;
+               return;
        }
 
        switch (rtm->rtm_type) {
@@ -1403,12 +1408,14 @@ static int kernel_read(struct thread *thread)
                        zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type);
                break;
        }
-       return 0;
 }
 
 /* Make routing socket. */
 static void routing_socket(struct zebra_ns *zns)
 {
+       uint32_t default_rcvbuf;
+       socklen_t optlen;
+
        frr_with_privs(&zserv_privs) {
                routing_sock = ns_socket(AF_ROUTE, SOCK_RAW, 0, zns->ns_id);
 
@@ -1443,6 +1450,23 @@ static void routing_socket(struct zebra_ns *zns)
        /*if (fcntl (routing_sock, F_SETFL, O_NONBLOCK) < 0)
          zlog_warn ("Can't set O_NONBLOCK to routing socket");*/
 
+       /*
+        * Attempt to set a more useful receive buffer size
+        */
+       optlen = sizeof(default_rcvbuf);
+       if (getsockopt(routing_sock, SOL_SOCKET, SO_RCVBUF, &default_rcvbuf,
+                      &optlen) == -1)
+               flog_err_sys(EC_LIB_SOCKET,
+                            "routing_sock sockopt SOL_SOCKET SO_RCVBUF");
+       else {
+               for (; rcvbufsize > default_rcvbuf &&
+                      setsockopt(routing_sock, SOL_SOCKET, SO_RCVBUF,
+                                 &rcvbufsize, sizeof(rcvbufsize)) == -1 &&
+                      errno == ENOBUFS;
+                    rcvbufsize /= 2)
+                       ;
+       }
+
        /* kernel_read needs rewrite. */
        thread_add_read(zrouter.master, kernel_read, NULL, routing_sock, NULL);
 }
@@ -1459,6 +1483,20 @@ void kernel_terminate(struct zebra_ns *zns, bool complete)
        return;
 }
 
+/*
+ * Global init for platform-/OS-specific things
+ */
+void kernel_router_init(void)
+{
+}
+
+/*
+ * Global deinit for platform-/OS-specific things
+ */
+void kernel_router_terminate(void)
+{
+}
+
 /*
  * Called by the dplane pthread to read incoming OS messages and dispatch them.
  */