Skip to content

Commit

Permalink
pimd: support for vrf netns for pimd ( not complete)
Browse files Browse the repository at this point in the history
The changes include the initialisation of the namespace, as well as the
switch from context when operating under network sockets.
Also it includes the bind to a vrf socket when the vrf is not a vrf lite.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
  • Loading branch information
pguibert6WIND committed Jan 15, 2018
1 parent e3732b4 commit f6cd156
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 22 deletions.
20 changes: 13 additions & 7 deletions pimd/pim_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
static void pim_if_igmp_join_del_all(struct interface *ifp);
static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
struct in_addr group_addr,
struct in_addr source_addr);
struct in_addr source_addr,
struct vrf *vrf);

void pim_if_init(struct pim_instance *pim)
{
Expand Down Expand Up @@ -580,6 +581,7 @@ void pim_if_addr_add(struct connected *ifc)
struct listnode *nextnode;
struct igmp_join *ij;
int join_fd;
struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);

for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
nextnode, ij)) {
Expand All @@ -588,7 +590,7 @@ void pim_if_addr_add(struct connected *ifc)
close(ij->sock_fd);
join_fd = igmp_join_sock(
ifp->name, ifp->ifindex, ij->group_addr,
ij->source_addr);
ij->source_addr, vrf);
if (join_fd < 0) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
Expand Down Expand Up @@ -1211,18 +1213,21 @@ static struct igmp_join *igmp_join_find(struct list *join_list,
}

static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
struct in_addr group_addr, struct in_addr source_addr)
struct in_addr group_addr,
struct in_addr source_addr, struct vrf *vrf)
{
int join_fd;

join_fd = pim_socket_raw(IPPROTO_IGMP);
join_fd = pim_socket_raw(IPPROTO_IGMP, vrf);
if (join_fd < 0) {
return -1;
}

if (pim_socket_join_source(join_fd, ifindex, group_addr, source_addr,
ifname)) {
ifname, vrf)) {
vrf_switch_to_netns(vrf);
close(join_fd);
vrf_switchback_to_initial();
return -2;
}

Expand All @@ -1236,12 +1241,13 @@ static struct igmp_join *igmp_join_new(struct interface *ifp,
struct pim_interface *pim_ifp;
struct igmp_join *ij;
int join_fd;

struct vrf *vrf;
pim_ifp = ifp->info;
zassert(pim_ifp);

vrf = vrf_lookup_by_id(ifp->vrf_id);
join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
source_addr);
source_addr, vrf);
if (join_fd < 0) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
Expand Down
11 changes: 7 additions & 4 deletions pimd/pim_igmp_join.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ struct group_source_req {

static int pim_igmp_join_source(int fd, ifindex_t ifindex,
struct in_addr group_addr,
struct in_addr source_addr)
struct in_addr source_addr,
struct vrf *vrf)
{
struct group_source_req req;
struct sockaddr_in group;
struct sockaddr_in source;
int ret;

memset(&req, 0, sizeof(req));
memset(&group, 0, sizeof(group));
Expand All @@ -58,10 +60,11 @@ static int pim_igmp_join_source(int fd, ifindex_t ifindex,

req.gsr_interface = ifindex;

return setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req,
vrf_switch_to_netns(vrf);
ret = setsockopt(fd, SOL_IP, MCAST_JOIN_SOURCE_GROUP, &req,
sizeof(req));

return 0;
vrf_switchback_to_initial();
return ret;
}

#endif /* PIM_IGMP_JOIN_H */
2 changes: 2 additions & 0 deletions pimd/pim_instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <zebra.h>

#include "hash.h"
#include "ns.h"
#include "vrf.h"

#include "pimd.h"
Expand Down Expand Up @@ -211,6 +212,7 @@ static int pim_vrf_config_write(struct vty *vty)

void pim_vrf_init(void)
{
ns_init();
vrf_init(pim_vrf_new, pim_vrf_enable, pim_vrf_disable, pim_vrf_delete);

vrf_cmd_init(pim_vrf_config_write);
Expand Down
17 changes: 14 additions & 3 deletions pimd/pim_mroute.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ static int pim_mroute_set(struct pim_instance *pim, int enable)
zlog_err(
"pim_mroute_socket_enable: could not raise privs, %s",
safe_strerror(errno));

vrf_switch_to_netns(pim->vrf);
opt = pim->vrf->data.l.table_id;
err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_TABLE,
&opt, opt_len);
vrf_switchback_to_initial();
if (err) {
zlog_warn(
"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP, MRT_TABLE=%d): errno=%d: %s",
Expand All @@ -78,8 +79,10 @@ static int pim_mroute_set(struct pim_instance *pim, int enable)
safe_strerror(errno));
}

vrf_switch_to_netns(pim->vrf);
opt = enable ? MRT_INIT : MRT_DONE;
err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &opt, opt_len);
vrf_switchback_to_initial();
if (err) {
zlog_warn(
"%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s",
Expand All @@ -93,39 +96,47 @@ static int pim_mroute_set(struct pim_instance *pim, int enable)
if (enable) {
/* Linux and Solaris IP_PKTINFO */
opt = 1;
vrf_switch_to_netns(pim->vrf);
if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO, &opt,
sizeof(opt))) {
zlog_warn(
"Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
pim->mroute_socket, errno,
safe_strerror(errno));
}
vrf_switchback_to_initial();
}
#endif

vrf_switch_to_netns(pim->vrf);
setsockopt_so_recvbuf(pim->mroute_socket, 1024 * 1024 * 8);

flags = fcntl(pim->mroute_socket, F_GETFL, 0);
if (flags < 0) {
zlog_warn("Could not get flags on socket fd:%d %d %s",
pim->mroute_socket, errno, safe_strerror(errno));
vrf_switchback_to_initial();
close(pim->mroute_socket);
return -1;
}
if (fcntl(pim->mroute_socket, F_SETFL, flags | O_NONBLOCK)) {
zlog_warn("Could not set O_NONBLOCK on socket fd:%d %d %s",
pim->mroute_socket, errno, safe_strerror(errno));
close(pim->mroute_socket);
vrf_switchback_to_initial();
return -1;
}
vrf_switchback_to_initial();

if (enable) {
#if defined linux
int upcalls = IGMPMSG_WRVIFWHOLE;
opt = MRT_PIM;

vrf_switch_to_netns(pim->vrf);
err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &upcalls,
sizeof(upcalls));
vrf_switchback_to_initial();
if (err) {
zlog_warn(
"Failure to register for VIFWHOLE and WRONGVIF upcalls %d %s",
Expand Down Expand Up @@ -710,9 +721,9 @@ int pim_mroute_socket_enable(struct pim_instance *pim)
if (pimd_privs.change(ZPRIVS_RAISE))
zlog_err("pim_mroute_socket_enable: could not raise privs, %s",
safe_strerror(errno));

vrf_switch_to_netns(pim->vrf);
fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);

vrf_switchback_to_initial();
if (fd < 0) {
zlog_warn("Could not create mroute socket: errno=%d: %s", errno,
safe_strerror(errno));
Expand Down
14 changes: 9 additions & 5 deletions pimd/pim_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,16 @@

/* GLOBAL VARS */

int pim_socket_raw(int protocol)
int pim_socket_raw(int protocol, struct vrf *vrf)
{
int fd;

if (pimd_privs.change(ZPRIVS_RAISE))
zlog_err("pim_sockek_raw: could not raise privs, %s",
safe_strerror(errno));

vrf_switch_to_netns(vrf);
fd = socket(AF_INET, SOCK_RAW, protocol);
vrf_switchback_to_initial();

if (pimd_privs.change(ZPRIVS_LOWER))
zlog_err("pim_socket_raw: could not lower privs, %s",
Expand Down Expand Up @@ -116,8 +117,10 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp,
struct ip_mreq mreq;
#endif
int fd;
struct vrf *vrf;

fd = pim_socket_raw(protocol);
vrf = vrf_lookup_by_id(ifp->vrf_id);
fd = pim_socket_raw(protocol, vrf);
if (fd < 0) {
zlog_warn("Could not create multicast socket: errno=%d: %s",
errno, safe_strerror(errno));
Expand Down Expand Up @@ -323,9 +326,10 @@ int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr,
}

int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr,
struct in_addr source_addr, const char *ifname)
struct in_addr source_addr,
const char *ifname, struct vrf *vrf)
{
if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) {
if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr, vrf)) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<grp?>", group_addr, group_str,
Expand Down
5 changes: 3 additions & 2 deletions pimd/pim_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@

int pim_socket_bind(int fd, struct interface *ifp);
void pim_socket_ip_hdr(int fd);
int pim_socket_raw(int protocol);
int pim_socket_raw(int protocol, struct vrf *vrf);
int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp,
u_char loop);
int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr,
ifindex_t ifindex);
int pim_socket_join_source(int fd, ifindex_t ifindex, struct in_addr group_addr,
struct in_addr source_addr, const char *ifname);
struct in_addr source_addr,
const char *ifname, struct vrf *vrf);
int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
struct sockaddr_in *from, socklen_t *fromlen,
struct sockaddr_in *to, socklen_t *tolen,
Expand Down
4 changes: 3 additions & 1 deletion pimd/test_igmpv3_join.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <net/if.h>
#include <arpa/inet.h>

#include "vrf.h"
#include "if.h"
#include "pim_igmp_join.h"

Expand Down Expand Up @@ -124,7 +125,8 @@ int main(int argc, const char *argv[])
exit(1);
}

result = pim_igmp_join_source(fd, ifindex, group_addr, source_addr);
result = pim_igmp_join_source(fd, ifindex, group_addr,
source_addr, NULL);
if (result) {
fprintf(stderr,
"%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s\n",
Expand Down

0 comments on commit f6cd156

Please sign in to comment.