summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Zalamena <rzalamena@users.noreply.github.com>2020-10-07 12:07:09 -0300
committerGitHub <noreply@github.com>2020-10-07 12:07:09 -0300
commitbd407b54d26981f30a95bc316ea2ed965d070c53 (patch)
tree6f09c1a81a5e54dd214878ad52a8f0e0e318982b
parent9cfb2747adc875a7aaa7f99a45a65f65234a2004 (diff)
parent7df1f3623ec3fb47be4f3b8234c393067c69ab4d (diff)
Merge pull request #7058 from Niral-Networks/niral_dev_vrf_ospf6
ospf6d : Socket change for ospf6d vrf support.
-rw-r--r--ospf6d/ospf6_main.c6
-rw-r--r--ospf6d/ospf6_message.c18
-rw-r--r--ospf6d/ospf6_network.c54
-rw-r--r--ospf6d/ospf6_network.h10
-rw-r--r--ospf6d/ospf6_top.c42
-rw-r--r--ospf6d/ospf6_top.h5
-rw-r--r--ospf6d/ospf6d.c5
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)