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>
#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)
.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. */
if (ospf6) {
vrf = vrf_lookup_by_id(ospf6->vrf_id);
+ ospf6_serv_close(&ospf6->fd);
ospf6_delete(ospf6);
ospf6 = NULL;
} else
ospf6_asbr_terminate();
ospf6_lsa_terminate();
- ospf6_serv_close();
/* reverse access_list_init */
access_list_reset();
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));
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;
}
/* 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)
#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,
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
#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;
#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);
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(
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;
}
}
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;
}
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;
#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 */
#include "thread.h"
#include "command.h"
#include "defaults.h"
+#include "lib_errors.h"
#include "ospf6_proto.h"
#include "ospf6_message.h"
#include "ospf6_area.h"
#include "ospf6_interface.h"
#include "ospf6_neighbor.h"
+#include "ospf6_network.h"
#include "ospf6_flood.h"
#include "ospf6_asbr.h"
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);
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;
ospf6_distance_reset(o);
route_table_finish(o->distance_table);
+ XFREE(MTYPE_OSPF6_TOP, o->name);
XFREE(MTYPE_OSPF6_TOP, 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);
}
}
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);
if (ospf6 == NULL)
vty_out(vty, "OSPFv3 is not configured\n");
else {
+ ospf6_serv_close(&ospf6->fd);
ospf6_delete(ospf6);
ospf6 = NULL;
}
/* The relevant vrf_id */
vrf_id_t vrf_id;
+ char *name; /* VRF name */
+
/* my router id */
in_addr_t router_id;
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;
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 */
&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)