From 7df1f3623ec3fb47be4f3b8234c393067c69ab4d Mon Sep 17 00:00:00 2001 From: Kaushik Date: Sat, 5 Sep 2020 00:07:25 -0700 Subject: [PATCH] ospf6d : Socket change for ospf6d vrf support. 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 Signed-off-by: Kaushik --- ospf6d/ospf6_main.c | 6 ++--- ospf6d/ospf6_message.c | 18 ++++++++++---- ospf6d/ospf6_network.c | 54 ++++++++++++++++++++++++++---------------- ospf6d/ospf6_network.h | 10 ++++---- ospf6d/ospf6_top.c | 42 ++++++++++++++++++++++++-------- ospf6d/ospf6_top.h | 5 ++++ ospf6d/ospf6d.c | 5 ++-- 7 files changed, 94 insertions(+), 46 deletions(-) diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c index 182faf0038..8533c1b12c 100644 --- a/ospf6d/ospf6_main.c +++ b/ospf6d/ospf6_main.c @@ -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(); diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 4830b38a66..eb8c414d9b 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -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) diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c index 9a18680b8b..abbb180d45 100644 --- a/ospf6d/ospf6_network.c +++ b/ospf6d/ospf6_network.c @@ -26,18 +26,19 @@ #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; diff --git a/ospf6d/ospf6_network.h b/ospf6d/ospf6_network.h index 7fe6e33ff2..eeef0514f3 100644 --- a/ospf6d/ospf6_network.h +++ b/ospf6d/ospf6_network.h @@ -21,17 +21,17 @@ #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 */ diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 6f23051dc3..49b7e4f142 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -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; } diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 806b4da1cf..a78b05d565 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -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 */ diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 17e33902d9..e904482391 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -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)