ospfd: basic support for VRF NETNS backend

The change consists in taking into account of the VRF identifier upon
which the ospf socket is created. Moreover, if the VRF is a netns
backend, then it is not necessary to perform the bind operations to vrf
device.
Also, when a VRF instance is enabled, it informs ospf VRF, and automatically
OSPF VRF benefits from it. Reversely, when VRF instance is disabled,
then OSPF VRF will be disabled too.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2018-01-29 16:56:11 +01:00
parent 97896a91c2
commit 3c0eb8faa2
3 changed files with 29 additions and 42 deletions

View File

@ -169,42 +169,27 @@ int ospf_if_ipmulticast(struct ospf *top, struct prefix *p, ifindex_t ifindex)
return ret;
}
int ospf_bind_vrfdevice(struct ospf *ospf, int ospf_sock)
{
int ret = 0;
#ifdef SO_BINDTODEVICE
if (ospf && ospf->vrf_id != VRF_DEFAULT &&
ospf->vrf_id != VRF_UNKNOWN) {
ret = setsockopt(ospf_sock, SOL_SOCKET, SO_BINDTODEVICE,
ospf->name,
strlen(ospf->name));
if (ret < 0) {
int save_errno = errno;
zlog_warn("%s: Could not setsockopt SO_BINDTODEVICE %s",
__PRETTY_FUNCTION__,
safe_strerror(save_errno));
}
}
#endif
return ret;
}
int ospf_sock_init(struct ospf *ospf)
{
int ospf_sock;
int ret, hincl = 1;
int bufsize = (8 * 1024 * 1024);
/* silently ignore. already done */
if (ospf->fd > 0)
return -1;
if (ospf->vrf_id == VRF_UNKNOWN) {
/* silently return since VRF is not ready */
return -1;
}
if (ospfd_privs.change(ZPRIVS_RAISE)) {
zlog_err("ospf_sock_init: could not raise privs, %s",
safe_strerror(errno));
}
ospf_sock = socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP);
ospf_sock = vrf_socket(AF_INET, SOCK_RAW, IPPROTO_OSPFIGP,
ospf->vrf_id, ospf->name);
if (ospf_sock < 0) {
int save_errno = errno;
@ -216,12 +201,6 @@ int ospf_sock_init(struct ospf *ospf)
exit(1);
}
ret = ospf_bind_vrfdevice(ospf, ospf_sock);
if (ret < 0) {
close(ospf_sock);
goto out;
}
#ifdef IP_HDRINCL
/* we will include IP header with packet */
ret = setsockopt(ospf_sock, IPPROTO_IP, IP_HDRINCL, &hincl,

View File

@ -30,6 +30,5 @@ extern int ospf_if_add_alldrouters(struct ospf *, struct prefix *, ifindex_t);
extern int ospf_if_drop_alldrouters(struct ospf *, struct prefix *, ifindex_t);
extern int ospf_if_ipmulticast(struct ospf *, struct prefix *, ifindex_t);
extern int ospf_sock_init(struct ospf *ospf);
extern int ospf_bind_vrfdevice(struct ospf *, int);
#endif /* _ZEBRA_OSPF_NETWORK_H */

View File

@ -308,12 +308,6 @@ static struct ospf *ospf_new(u_short instance, const char *name)
new->lsa_refresh_interval, &new->t_lsa_refresher);
new->lsa_refresher_started = monotime(NULL);
if ((ospf_sock_init(new)) < 0) {
zlog_err(
"ospf_new: fatal error: ospf_sock_init was unable to open "
"a socket");
exit(1);
}
if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1)) == NULL) {
zlog_err(
"ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
@ -321,7 +315,6 @@ static struct ospf *ospf_new(u_short instance, const char *name)
exit(1);
}
new->t_read = NULL;
thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
new->oi_write_q = list_new();
new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT;
@ -332,6 +325,16 @@ static struct ospf *ospf_new(u_short instance, const char *name)
QOBJ_REG(new, ospf);
new->fd = -1;
if ((ospf_sock_init(new)) < 0) {
if (new->vrf_id != VRF_UNKNOWN)
zlog_warn(
"%s: ospf_sock_init is unable to open a socket",
__func__);
return new;
}
thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
return new;
}
@ -2050,6 +2053,7 @@ static int ospf_vrf_enable(struct vrf *vrf)
{
struct ospf *ospf = NULL;
vrf_id_t old_vrf_id;
int ret = 0;
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: VRF %s id %u enabled",
@ -2070,13 +2074,15 @@ static int ospf_vrf_enable(struct vrf *vrf)
zlog_err("ospf_sock_init: could not raise privs, %s",
safe_strerror(errno));
}
if (ospf_bind_vrfdevice(ospf, ospf->fd) < 0)
return 0;
ret = ospf_sock_init(ospf);
if (ospfd_privs.change(ZPRIVS_LOWER)) {
zlog_err("ospf_sock_init: could not lower privs, %s",
safe_strerror(errno));
}
if (ret < 0 || ospf->fd <= 0)
return 0;
thread_add_read(master, ospf_read, ospf,
ospf->fd, &ospf->t_read);
ospf->oi_running = 1;
ospf_zebra_vrf_register(ospf);
ospf_router_id_update(ospf);
@ -2111,6 +2117,9 @@ static int ospf_vrf_disable(struct vrf *vrf)
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf old_vrf_id %d unlinked",
__PRETTY_FUNCTION__, old_vrf_id);
thread_cancel(ospf->t_read);
close(ospf->fd);
ospf->fd = -1;
}
/* Note: This is a callback, the VRF will be deleted by the caller. */