]> git.puffer.fish Git - mirror/frr.git/commitdiff
ospf6d : Socket change for ospf6d vrf support. 7058/head
authorKaushik <kaushik@niralnetworks.com>
Sat, 5 Sep 2020 07:07:25 +0000 (00:07 -0700)
committerKaushik <kaushik@niralnetworks.com>
Wed, 7 Oct 2020 04:23:54 +0000 (21:23 -0700)
1. The socket() call is changed to vrf_socket().
2. The ospf6 instance creation api added.
3. The global socket fd is replaced with ospf6->fd.
4. All dependency of the global socket is resolved.
5. Added the ospf6 receive timer in the global structure.
6. Performed the thread off on receive timer when we do "no router ospf6".

Co-authored-by: harios <hari@niralnetworks.com>
Signed-off-by: Kaushik <kaushik@niralnetworks.com>
ospf6d/ospf6_main.c
ospf6d/ospf6_message.c
ospf6d/ospf6_network.c
ospf6d/ospf6_network.h
ospf6d/ospf6_top.c
ospf6d/ospf6_top.h
ospf6d/ospf6d.c

index 182faf0038f4eb28af67a94861bba901060861e4..8533c1b12c98d59cc7b1ee04955526eb494c467e 100644 (file)
@@ -55,7 +55,7 @@
 #define OSPF6_VTY_PORT             2606
 
 /* ospf6d privileges */
-zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND};
+zebra_capabilities_t _caps_p[] = {ZCAP_NET_RAW, ZCAP_BIND, ZCAP_SYS_ADMIN};
 
 struct zebra_privs_t ospf6d_privs = {
 #if defined(FRR_USER)
@@ -68,7 +68,7 @@ struct zebra_privs_t ospf6d_privs = {
        .vty_group = VTY_GROUP,
 #endif
        .caps_p = _caps_p,
-       .cap_num_p = 2,
+       .cap_num_p = array_size(_caps_p),
        .cap_num_i = 0};
 
 /* ospf6d options, we use GNU getopt library. */
@@ -86,6 +86,7 @@ static void __attribute__((noreturn)) ospf6_exit(int status)
 
        if (ospf6) {
                vrf = vrf_lookup_by_id(ospf6->vrf_id);
+               ospf6_serv_close(&ospf6->fd);
                ospf6_delete(ospf6);
                ospf6 = NULL;
        } else
@@ -101,7 +102,6 @@ static void __attribute__((noreturn)) ospf6_exit(int status)
        ospf6_asbr_terminate();
        ospf6_lsa_terminate();
 
-       ospf6_serv_close();
        /* reverse access_list_init */
        access_list_reset();
 
index 4830b38a66614496dcafcda2d238cc6f2dd47cab..eb8c414d9b015263efe82f6d5cc728217d293277 100644 (file)
@@ -1532,10 +1532,14 @@ int ospf6_receive(struct thread *thread)
        struct iovec iovector[2];
        struct ospf6_interface *oi;
        struct ospf6_header *oh;
+       struct ospf6 *ospf6;
 
        /* add next read thread */
+       ospf6 = THREAD_ARG(thread);
        sockfd = THREAD_FD(thread);
-       thread_add_read(master, ospf6_receive, NULL, sockfd, NULL);
+
+       thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
+                       &ospf6->t_ospf6_receive);
 
        /* initialize */
        memset(&src, 0, sizeof(src));
@@ -1548,7 +1552,7 @@ int ospf6_receive(struct thread *thread)
        iovector[1].iov_len = 0;
 
        /* receive message */
-       len = ospf6_recvmsg(&src, &dst, &ifindex, iovector);
+       len = ospf6_recvmsg(&src, &dst, &ifindex, iovector, sockfd);
        if (len > iobuflen) {
                flog_err(EC_LIB_DEVELOPMENT, "Excess message read");
                return 0;
@@ -1696,9 +1700,13 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
        }
 
        /* send message */
-       len = ospf6_sendmsg(src, dst, &oi->interface->ifindex, iovector);
-       if (len != ntohs(oh->length))
-               flog_err(EC_LIB_DEVELOPMENT, "Could not send entire message");
+       if (oi->area->ospf6->fd != -1) {
+               len = ospf6_sendmsg(src, dst, &oi->interface->ifindex, iovector,
+                                   oi->area->ospf6->fd);
+               if (len != ntohs(oh->length))
+                       flog_err(EC_LIB_DEVELOPMENT,
+                                "Could not send entire message");
+       }
 }
 
 static uint32_t ospf6_packet_max(struct ospf6_interface *oi)
index 9a18680b8b532c1a2fa16b430c58ab2d9fafeaae..abbb180d45642f7ec3c3df794c940574474f0ca9 100644 (file)
 #include "sockopt.h"
 #include "privs.h"
 #include "lib_errors.h"
+#include "vrf.h"
 
 #include "libospf.h"
 #include "ospf6_proto.h"
 #include "ospf6_network.h"
 #include "ospf6d.h"
+#include "ospf6_top.h"
 
-int ospf6_sock;
 struct in6_addr allspfrouters6;
 struct in6_addr alldrouters6;
 
 /* setsockopt MulticastLoop to off */
-static void ospf6_reset_mcastloop(void)
+static void ospf6_reset_mcastloop(int ospf6_sock)
 {
        unsigned int off = 0;
        if (setsockopt(ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off,
@@ -47,19 +48,19 @@ static void ospf6_reset_mcastloop(void)
                          safe_strerror(errno));
 }
 
-static void ospf6_set_pktinfo(void)
+static void ospf6_set_pktinfo(int ospf6_sock)
 {
        setsockopt_ipv6_pktinfo(ospf6_sock, 1);
 }
 
-static void ospf6_set_transport_class(void)
+static void ospf6_set_transport_class(int ospf6_sock)
 {
 #ifdef IPTOS_PREC_INTERNETCONTROL
        setsockopt_ipv6_tclass(ospf6_sock, IPTOS_PREC_INTERNETCONTROL);
 #endif
 }
 
-static void ospf6_set_checksum(void)
+static void ospf6_set_checksum(int ospf6_sock)
 {
        int offset = 12;
 #ifndef DISABLE_IPV6_CHECKSUM
@@ -73,21 +74,30 @@ static void ospf6_set_checksum(void)
 #endif /* DISABLE_IPV6_CHECKSUM */
 }
 
-void ospf6_serv_close(void)
+void ospf6_serv_close(int *ospf6_sock)
 {
-       if (ospf6_sock > 0) {
-               close(ospf6_sock);
-               ospf6_sock = -1;
+       if (*ospf6_sock != -1) {
+               close(*ospf6_sock);
+               *ospf6_sock = -1;
                return;
        }
 }
 
 /* Make ospf6d's server socket. */
-int ospf6_serv_sock(void)
+int ospf6_serv_sock(struct ospf6 *ospf6)
 {
+       int ospf6_sock;
+
+       if (ospf6->fd != -1)
+               return -1;
+
+       if (ospf6->vrf_id == VRF_UNKNOWN)
+               return -1;
+
        frr_with_privs(&ospf6d_privs) {
 
-               ospf6_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
+               ospf6_sock = vrf_socket(AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP,
+                                       ospf6->vrf_id, ospf6->name);
                if (ospf6_sock < 0) {
                        zlog_warn("Network: can't create OSPF6 socket.");
                        return -1;
@@ -100,11 +110,12 @@ int ospf6_serv_sock(void)
 #else
        ospf6_set_reuseaddr();
 #endif /*1*/
-       ospf6_reset_mcastloop();
-       ospf6_set_pktinfo();
-       ospf6_set_transport_class();
-       ospf6_set_checksum();
+       ospf6_reset_mcastloop(ospf6_sock);
+       ospf6_set_pktinfo(ospf6_sock);
+       ospf6_set_transport_class(ospf6_sock);
+       ospf6_set_checksum(ospf6_sock);
 
+       ospf6->fd = ospf6_sock;
        /* setup global in6_addr, allspf6 and alldr6 for later use */
        inet_pton(AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
        inet_pton(AF_INET6, ALLDROUTERS6, &alldrouters6);
@@ -119,11 +130,14 @@ int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option)
        int ret;
        int bufsize = (8 * 1024 * 1024);
 
+       if (ospf6->fd == -1)
+               return -1;
+
        assert(ifindex);
        mreq6.ipv6mr_interface = ifindex;
        memcpy(&mreq6.ipv6mr_multiaddr, group, sizeof(struct in6_addr));
 
-       ret = setsockopt(ospf6_sock, IPPROTO_IPV6, option, &mreq6,
+       ret = setsockopt(ospf6->fd, IPPROTO_IPV6, option, &mreq6,
                         sizeof(mreq6));
        if (ret < 0) {
                flog_err_sys(
@@ -133,8 +147,8 @@ int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option)
                return ret;
        }
 
-       setsockopt_so_sendbuf(ospf6_sock, bufsize);
-       setsockopt_so_recvbuf(ospf6_sock, bufsize);
+       setsockopt_so_sendbuf(ospf6->fd, bufsize);
+       setsockopt_so_recvbuf(ospf6->fd, bufsize);
 
        return 0;
 }
@@ -157,7 +171,7 @@ static int iov_totallen(struct iovec *iov)
 }
 
 int ospf6_sendmsg(struct in6_addr *src, struct in6_addr *dst,
-                 ifindex_t *ifindex, struct iovec *message)
+                 ifindex_t *ifindex, struct iovec *message, int ospf6_sock)
 {
        int retval;
        struct msghdr smsghdr;
@@ -216,7 +230,7 @@ int ospf6_sendmsg(struct in6_addr *src, struct in6_addr *dst,
 }
 
 int ospf6_recvmsg(struct in6_addr *src, struct in6_addr *dst,
-                 ifindex_t *ifindex, struct iovec *message)
+                 ifindex_t *ifindex, struct iovec *message, int ospf6_sock)
 {
        int retval;
        struct msghdr rmsghdr;
index 7fe6e33ff2b724f50976861d824f325368b785d5..eeef0514f347aaa320519f0b4619a71a9e069d43 100644 (file)
 #ifndef OSPF6_NETWORK_H
 #define OSPF6_NETWORK_H
 
-extern int ospf6_sock;
+struct ospf6 *ospf6;
 extern struct in6_addr allspfrouters6;
 extern struct in6_addr alldrouters6;
 
-extern int ospf6_serv_sock(void);
-extern void ospf6_serv_close(void);
+extern int ospf6_serv_sock(struct ospf6 *ospf6);
+extern void ospf6_serv_close(int *ospf6_sock);
 extern int ospf6_sso(ifindex_t ifindex, struct in6_addr *group, int option);
 
 extern int ospf6_sendmsg(struct in6_addr *, struct in6_addr *, ifindex_t *,
-                        struct iovec *);
+                        struct iovec *, int ospf6_sock);
 extern int ospf6_recvmsg(struct in6_addr *, struct in6_addr *, ifindex_t *,
-                        struct iovec *);
+                        struct iovec *, int ospf6_sock);
 
 #endif /* OSPF6_NETWORK_H */
index 6f23051dc3e32f85dedc22419d2c3ea27a4f424d..49b7e4f1429667a5cfd2971a17be44953f46b721 100644 (file)
@@ -29,6 +29,7 @@
 #include "thread.h"
 #include "command.h"
 #include "defaults.h"
+#include "lib_errors.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_message.h"
@@ -41,6 +42,7 @@
 #include "ospf6_area.h"
 #include "ospf6_interface.h"
 #include "ospf6_neighbor.h"
+#include "ospf6_network.h"
 
 #include "ospf6_flood.h"
 #include "ospf6_asbr.h"
@@ -141,15 +143,21 @@ static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
        ospf6_abr_originate_summary(route);
 }
 
-static struct ospf6 *ospf6_create(vrf_id_t vrf_id)
+static struct ospf6 *ospf6_create(const char *name)
 {
        struct ospf6 *o;
+       struct vrf *vrf = NULL;
 
        o = XCALLOC(MTYPE_OSPF6_TOP, sizeof(struct ospf6));
 
+       vrf = vrf_lookup_by_name(name);
+       if (vrf) {
+               o->vrf_id = vrf->vrf_id;
+               /* Freed in ospf6_delete */
+               o->name = XSTRDUP(MTYPE_OSPF6_TOP, name);
+       }
        /* initialize */
        monotime(&o->starttime);
-       o->vrf_id = vrf_id;
        o->area_list = list_new();
        o->area_list->cmp = ospf6_area_cmp;
        o->lsdb = ospf6_lsdb_create(o);
@@ -183,12 +191,28 @@ static struct ospf6 *ospf6_create(vrf_id_t vrf_id)
        o->ref_bandwidth = OSPF6_REFERENCE_BANDWIDTH;
 
        o->distance_table = route_table_init();
+       o->fd = -1;
 
        QOBJ_REG(o, ospf6);
 
+       /* Make ospf protocol socket. */
+       ospf6_serv_sock(o);
+
        return o;
 }
 
+void ospf6_instance_create(const char *name)
+{
+       ospf6 = ospf6_create(name);
+       if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
+               SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
+       if (ospf6->router_id == 0)
+               ospf6_router_id_update();
+
+       thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
+                       &ospf6->t_ospf6_receive);
+}
+
 void ospf6_delete(struct ospf6 *o)
 {
        struct listnode *node, *nnode;
@@ -217,6 +241,7 @@ void ospf6_delete(struct ospf6 *o)
        ospf6_distance_reset(o);
        route_table_finish(o->distance_table);
 
+       XFREE(MTYPE_OSPF6_TOP, o->name);
        XFREE(MTYPE_OSPF6_TOP, o);
 }
 
@@ -242,6 +267,7 @@ static void ospf6_disable(struct ospf6 *o)
                THREAD_OFF(o->t_spf_calc);
                THREAD_OFF(o->t_ase_calc);
                THREAD_OFF(o->t_distribute_update);
+               THREAD_OFF(o->t_ospf6_receive);
        }
 }
 
@@ -325,14 +351,9 @@ DEFUN_NOSH (router_ospf6,
        ROUTER_STR
        OSPF6_STR)
 {
-       if (ospf6 == NULL) {
-               ospf6 = ospf6_create(VRF_DEFAULT);
-               if (DFLT_OSPF6_LOG_ADJACENCY_CHANGES)
-                       SET_FLAG(ospf6->config_flags,
-                                OSPF6_LOG_ADJACENCY_CHANGES);
-               if (ospf6->router_id == 0)
-                       ospf6_router_id_update();
-       }
+       if (ospf6 == NULL)
+               ospf6_instance_create(VRF_DEFAULT_NAME);
+
        /* set current ospf point. */
        VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
 
@@ -350,6 +371,7 @@ DEFUN (no_router_ospf6,
        if (ospf6 == NULL)
                vty_out(vty, "OSPFv3 is not configured\n");
        else {
+               ospf6_serv_close(&ospf6->fd);
                ospf6_delete(ospf6);
                ospf6 = NULL;
        }
index 806b4da1cfbc80d0a4ca75521ad4c0291777037a..a78b05d565ece7d786d1a532fd78098c961e7554 100644 (file)
@@ -40,6 +40,8 @@ struct ospf6 {
        /* The relevant vrf_id */
        vrf_id_t vrf_id;
 
+       char *name; /* VRF name */
+
        /* my router id */
        in_addr_t router_id;
 
@@ -92,11 +94,13 @@ struct ospf6 {
        struct timeval ts_spf_duration; /* Execution time of last SPF */
        unsigned int last_spf_reason;   /* Last SPF reason */
 
+       int fd;
        /* Threads */
        struct thread *t_spf_calc; /* SPF calculation timer. */
        struct thread *t_ase_calc; /* ASE calculation timer. */
        struct thread *maxage_remover;
        struct thread *t_distribute_update; /* Distirbute update timer. */
+       struct thread *t_ospf6_receive; /* OSPF6 receive timer */
 
        uint32_t ref_bandwidth;
 
@@ -130,5 +134,6 @@ extern void ospf6_delete(struct ospf6 *o);
 extern void ospf6_router_id_update(void);
 
 extern void ospf6_maxage_remove(struct ospf6 *o);
+extern void ospf6_instance_create(const char *name);
 
 #endif /* OSPF6_TOP_H */
index 17e33902d9a18d9f06dbfc73a899e54b99756f67..e90448239106b59b43024809c51d19b0d93a45fb 100644 (file)
@@ -1268,9 +1268,8 @@ void ospf6_init(void)
                &show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd);
        install_element(VIEW_NODE, &show_ipv6_ospf6_database_aggr_router_cmd);
 
-       /* Make ospf protocol socket. */
-       ospf6_serv_sock();
-       thread_add_read(master, ospf6_receive, NULL, ospf6_sock, NULL);
+       if (ospf6 == NULL)
+               ospf6_instance_create(VRF_DEFAULT_NAME);
 }
 
 void ospf6_clean(void)