Skip to content

Commit

Permalink
bgpd: server socket is created for all enabled VRF
Browse files Browse the repository at this point in the history
Upon creation of BGP instances, server socket may or may not be created.
In the case of VRF instances, if the VRF backend relies on NETNS, then
a new server socket will be created for each BGP VRF instance. If the
VRF backend relies on VRF LITE, then only one server socket will be
enough. Moreover, At startup, with BGP VRF configuration, a server
socket may not be created if VRF is not the default one or VRF is not
recognized yet.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
  • Loading branch information
pguibert6WIND committed Feb 27, 2018
1 parent 61cf4b3 commit e5619c2
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 13 deletions.
2 changes: 2 additions & 0 deletions bgpd/bgp_main.c
Expand Up @@ -261,6 +261,7 @@ static int bgp_vrf_enable(struct vrf *vrf)
/* We have instance configured, link to VRF and make it "up". */
bgp_vrf_link(bgp, vrf);

bgp_handle_socket(bgp, vrf, old_vrf_id, true);
/* Update any redistribute vrf bitmaps if the vrf_id changed */
if (old_vrf_id != bgp->vrf_id)
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
Expand All @@ -284,6 +285,7 @@ static int bgp_vrf_disable(struct vrf *vrf)
bgp = bgp_lookup_by_name(vrf->name);
if (bgp) {
old_vrf_id = bgp->vrf_id;
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
/* We have instance configured, unlink from VRF and make it
* "down". */
bgp_vrf_unlink(bgp, vrf);
Expand Down
28 changes: 28 additions & 0 deletions bgpd/bgp_network.c
Expand Up @@ -781,6 +781,32 @@ int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
return 0;
}

/* this function closes vrf socket
* this should be called only for vrf socket with netns backend
*/
void bgp_close_vrf_socket(struct bgp *bgp)
{
struct listnode *node, *next;
struct bgp_listener *listener;

if (!bgp)
return;

if (bm->listen_sockets == NULL)
return;

for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
if (listener->bgp == bgp) {
thread_cancel(listener->thread);
close(listener->fd);
listnode_delete(bm->listen_sockets, listener);
XFREE(MTYPE_BGP_LISTENER, listener);
}
}
}

/* this function closes main socket
*/
void bgp_close(void)
{
struct listnode *node, *next;
Expand All @@ -790,6 +816,8 @@ void bgp_close(void)
return;

for (ALL_LIST_ELEMENTS(bm->listen_sockets, node, next, listener)) {
if (listener->bgp)
continue;
thread_cancel(listener->thread);
close(listener->fd);
listnode_delete(bm->listen_sockets, listener);
Expand Down
1 change: 1 addition & 0 deletions bgpd/bgp_network.h
Expand Up @@ -25,6 +25,7 @@

extern int bgp_socket(struct bgp *bgp, unsigned short port,
const char *address);
extern void bgp_close_vrf_socket(struct bgp *bgp);
extern void bgp_close(void);
extern int bgp_connect(struct peer *);
extern int bgp_getsockname(struct peer *);
Expand Down
111 changes: 98 additions & 13 deletions bgpd/bgpd.c
Expand Up @@ -101,6 +101,42 @@ static void bgp_if_finish(struct bgp *bgp);

extern struct zclient *zclient;

/* handle main socket creation or deletion */
static int bgp_check_main_socket(bool create, struct bgp *bgp)
{
static int bgp_server_main_created;
struct listnode *bgpnode, *nbgpnode;
struct bgp *bgp_temp;

if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
return 0;
if (create == true) {
if (bgp_server_main_created)
return 0;
if (bgp_socket(bgp, bm->port, bm->address) < 0)
return BGP_ERR_INVALID_VALUE;
bgp_server_main_created = 1;
return 0;
}
if (!bgp_server_main_created)
return 0;
/* only delete socket on some cases */
for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp_temp)) {
/* do not count with current bgp */
if (bgp_temp == bgp)
continue;
/* if other instance non VRF, do not delete socket */
if (bgp_temp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
return 0;
/* vrf lite, do not delete socket */
if (!vrf_is_mapped_on_netns(bgp_temp->vrf_id))
return 0;
}
bgp_close();
bgp_server_main_created = 0;
return 0;
}

void bgp_session_reset(struct peer *peer)
{
if (peer->doppelganger && (peer->doppelganger->status != Deleted)
Expand Down Expand Up @@ -2981,11 +3017,67 @@ struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
return (vrf->info) ? (struct bgp *)vrf->info : NULL;
}

/* handle socket creation or deletion, if necessary
* this is called for all new BGP instances
*/
int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf,
vrf_id_t old_vrf_id, bool create)
{
int ret = 0;

/* Create BGP server socket, if listen mode not disabled */
if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN))
return 0;
if (bgp->name
&& bgp->inst_type == BGP_INSTANCE_TYPE_VRF
&& vrf) {
/*
* suppress vrf socket
*/
if (create == FALSE) {
if (vrf_is_mapped_on_netns(vrf->vrf_id))
bgp_close_vrf_socket(bgp);
else
ret = bgp_check_main_socket(create, bgp);
return ret;
}
/* do nothing
* if vrf_id did not change
*/
if (vrf->vrf_id == old_vrf_id)
return 0;
if (old_vrf_id != VRF_UNKNOWN) {
/* look for old socket. close it. */
bgp_close_vrf_socket(bgp);
}
/* if backend is not yet identified ( VRF_UNKNOWN) then
* creation will be done later
*/
if (vrf->vrf_id == VRF_UNKNOWN)
return 0;
/* if BGP VRF instance requested
* if backend is NETNS, create BGP server socket in the NETNS
*/
if (vrf_is_mapped_on_netns(bgp->vrf_id)) {
ret = bgp_socket(bgp, bm->port, bm->address);
if (ret < 0)
return BGP_ERR_INVALID_VALUE;
return 0;
}
}
/* if BGP VRF instance requested or VRF lite backend
* if BGP non VRF instance, create it
* if not already done
*/
return bgp_check_main_socket(create, bgp);
}

/* Called from VTY commands. */
int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
enum bgp_instance_type inst_type)
{
struct bgp *bgp;
struct vrf *vrf = NULL;

/* Multiple instance check. */
if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
Expand Down Expand Up @@ -3033,25 +3125,19 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,

bgp->t_rmap_def_originate_eval = NULL;

/* Create BGP server socket, if first instance. */
if (list_isempty(bm->bgp) && !bgp_option_check(BGP_OPT_NO_LISTEN)) {
if (bgp_socket(bgp, bm->port, bm->address) < 0)
return BGP_ERR_INVALID_VALUE;
}

listnode_add(bm->bgp, bgp);

/* If Default instance or VRF, link to the VRF structure, if present. */
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
|| bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
struct vrf *vrf;

vrf = bgp_vrf_lookup_by_instance_type(bgp);
if (vrf)
bgp_vrf_link(bgp, vrf);
}
/* BGP server socket already processed if BGP instance
* already part of the list
*/
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, true);
listnode_add(bm->bgp, bgp);

/* Register with Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
bgp_zebra_instance_register(bgp);

Expand Down Expand Up @@ -3188,8 +3274,6 @@ int bgp_delete(struct bgp *bgp)
* routes to be processed still referencing the struct bgp.
*/
listnode_delete(bm->bgp, bgp);
if (list_isempty(bm->bgp))
bgp_close();

/* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
Expand All @@ -3199,6 +3283,7 @@ int bgp_delete(struct bgp *bgp)
bgp_if_finish(bgp);

vrf = bgp_vrf_lookup_by_instance_type(bgp);
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
if (vrf)
bgp_vrf_unlink(bgp, vrf);

Expand Down
3 changes: 3 additions & 0 deletions bgpd/bgpd.h
Expand Up @@ -1355,6 +1355,9 @@ extern void bgp_instance_up(struct bgp *);
extern void bgp_instance_down(struct bgp *);
extern int bgp_delete(struct bgp *);

extern int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf,
vrf_id_t old_vrf_id, bool create);

extern int bgp_flag_set(struct bgp *, int);
extern int bgp_flag_unset(struct bgp *, int);
extern int bgp_flag_check(struct bgp *, int);
Expand Down

0 comments on commit e5619c2

Please sign in to comment.