Merge pull request #4885 from satheeshkarra/pim_mlag

pimd, lib, Zebra: PIM MLAG Support
This commit is contained in:
Jafar Al-Gharaibeh 2019-10-14 01:07:24 -05:00 committed by GitHub
commit d563896dad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 2749 additions and 22 deletions

View File

@ -125,6 +125,7 @@ include doc/manpages/subdir.am
include doc/developer/subdir.am
include include/subdir.am
include lib/subdir.am
include mlag/subdir.am
include zebra/subdir.am
include watchfrr/subdir.am
include qpb/subdir.am

View File

@ -39,3 +39,133 @@ char *mlag_role2str(enum mlag_role role, char *buf, size_t size)
return buf;
}
char *zebra_mlag_lib_msgid_to_str(enum mlag_msg_type msg_type, char *buf,
size_t size)
{
switch (msg_type) {
case MLAG_REGISTER:
snprintf(buf, size, "Register");
break;
case MLAG_DEREGISTER:
snprintf(buf, size, "De-Register");
break;
case MLAG_MROUTE_ADD:
snprintf(buf, size, "Mroute add");
break;
case MLAG_MROUTE_DEL:
snprintf(buf, size, "Mroute del");
break;
case MLAG_DUMP:
snprintf(buf, size, "Mlag Replay");
break;
case MLAG_MROUTE_ADD_BULK:
snprintf(buf, size, "Mroute Add Batch");
break;
case MLAG_MROUTE_DEL_BULK:
snprintf(buf, size, "Mroute Del Batch");
break;
case MLAG_STATUS_UPDATE:
snprintf(buf, size, "Mlag Status");
break;
case MLAG_VXLAN_UPDATE:
snprintf(buf, size, "Mlag vxlan update");
break;
case MLAG_PEER_FRR_STATUS:
snprintf(buf, size, "Mlag Peer FRR Status");
break;
default:
snprintf(buf, size, "Unknown %d", msg_type);
break;
}
return buf;
}
int zebra_mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GETL(s, msg->msg_type);
STREAM_GETW(s, msg->data_len);
STREAM_GETW(s, msg->msg_cnt);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_mroute_add(struct stream *s,
struct mlag_mroute_add *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GET(msg->vrf_name, s, VRF_NAMSIZ);
STREAM_GETL(s, msg->source_ip);
STREAM_GETL(s, msg->group_ip);
STREAM_GETL(s, msg->cost_to_rp);
STREAM_GETL(s, msg->owner_id);
STREAM_GETC(s, msg->am_i_dr);
STREAM_GETC(s, msg->am_i_dual_active);
STREAM_GETL(s, msg->vrf_id);
STREAM_GET(msg->intf_name, s, INTERFACE_NAMSIZ);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_mroute_del(struct stream *s,
struct mlag_mroute_del *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GET(msg->vrf_name, s, VRF_NAMSIZ);
STREAM_GETL(s, msg->source_ip);
STREAM_GETL(s, msg->group_ip);
STREAM_GETL(s, msg->owner_id);
STREAM_GETL(s, msg->vrf_id);
STREAM_GET(msg->intf_name, s, INTERFACE_NAMSIZ);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_mlag_status(struct stream *s, struct mlag_status *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GET(msg->peerlink_rif, s, INTERFACE_NAMSIZ);
STREAM_GETL(s, msg->my_role);
STREAM_GETL(s, msg->peer_state);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_vxlan_update(struct stream *s, struct mlag_vxlan *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GETL(s, msg->anycast_ip);
STREAM_GETL(s, msg->local_ip);
return 0;
stream_failure:
return -1;
}
int zebra_mlag_lib_decode_frr_status(struct stream *s,
struct mlag_frr_status *msg)
{
if (s == NULL || msg == NULL)
return -1;
STREAM_GETL(s, msg->frr_state);
return 0;
stream_failure:
return -1;
}

View File

@ -26,13 +26,118 @@
extern "C" {
#endif
#include "lib/if.h"
#include "lib/vrf.h"
#include "lib/stream.h"
#define MLAG_MSG_NULL_PAYLOAD 0
#define MLAG_MSG_NO_BATCH 1
#define MLAG_BUF_LIMIT 2048
enum mlag_role {
MLAG_ROLE_NONE,
MLAG_ROLE_PRIMARY,
MLAG_ROLE_SECONDARY
};
enum mlag_state {
MLAG_STATE_DOWN,
MLAG_STATE_RUNNING,
};
enum mlag_frr_state {
MLAG_FRR_STATE_NONE,
MLAG_FRR_STATE_DOWN,
MLAG_FRR_STATE_UP,
};
enum mlag_owner {
MLAG_OWNER_NONE,
MLAG_OWNER_INTERFACE,
MLAG_OWNER_VXLAN,
};
/*
* This message definition should match mlag.proto
* Because message registration is based on this
*/
enum mlag_msg_type {
MLAG_MSG_NONE = 0,
MLAG_REGISTER = 1,
MLAG_DEREGISTER = 2,
MLAG_STATUS_UPDATE = 3,
MLAG_MROUTE_ADD = 4,
MLAG_MROUTE_DEL = 5,
MLAG_DUMP = 6,
MLAG_MROUTE_ADD_BULK = 7,
MLAG_MROUTE_DEL_BULK = 8,
MLAG_PIM_CFG_DUMP = 10,
MLAG_VXLAN_UPDATE = 11,
MLAG_PEER_FRR_STATUS = 12,
};
struct mlag_frr_status {
enum mlag_frr_state frr_state;
};
struct mlag_status {
char peerlink_rif[INTERFACE_NAMSIZ];
enum mlag_role my_role;
enum mlag_state peer_state;
};
#define MLAG_ROLE_STRSIZE 16
struct mlag_vxlan {
uint32_t anycast_ip;
uint32_t local_ip;
};
struct mlag_mroute_add {
char vrf_name[VRF_NAMSIZ];
uint32_t source_ip;
uint32_t group_ip;
uint32_t cost_to_rp;
enum mlag_owner owner_id;
uint8_t am_i_dr;
uint8_t am_i_dual_active;
uint32_t vrf_id;
char intf_name[INTERFACE_NAMSIZ];
};
struct mlag_mroute_del {
char vrf_name[VRF_NAMSIZ];
uint32_t source_ip;
uint32_t group_ip;
enum mlag_owner owner_id;
uint32_t vrf_id;
char intf_name[INTERFACE_NAMSIZ];
};
struct mlag_msg {
enum mlag_msg_type msg_type;
uint16_t data_len;
uint16_t msg_cnt;
uint8_t data[0];
};
extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
extern char *zebra_mlag_lib_msgid_to_str(enum mlag_msg_type msg_type, char *buf,
size_t size);
extern int zebra_mlag_lib_decode_mlag_hdr(struct stream *s,
struct mlag_msg *msg);
extern int zebra_mlag_lib_decode_mroute_add(struct stream *s,
struct mlag_mroute_add *msg);
extern int zebra_mlag_lib_decode_mroute_del(struct stream *s,
struct mlag_mroute_del *msg);
extern int zebra_mlag_lib_decode_mlag_status(struct stream *s,
struct mlag_status *msg);
extern int zebra_mlag_lib_decode_vxlan_update(struct stream *s,
struct mlag_vxlan *msg);
extern int zebra_mlag_lib_decode_frr_status(struct stream *s,
struct mlag_frr_status *msg);
#ifdef __cplusplus
}

View File

@ -2717,6 +2717,63 @@ stream_failure:
return;
}
void zclient_send_mlag_register(struct zclient *client, uint32_t bit_map)
{
struct stream *s;
s = client->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_MLAG_CLIENT_REGISTER, VRF_DEFAULT);
stream_putl(s, bit_map);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(client);
}
void zclient_send_mlag_deregister(struct zclient *client)
{
zebra_message_send(client, ZEBRA_MLAG_CLIENT_UNREGISTER, VRF_DEFAULT);
}
void zclient_send_mlag_data(struct zclient *client, struct stream *client_s)
{
struct stream *s;
s = client->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_MLAG_FORWARD_MSG, VRF_DEFAULT);
stream_put(s, client_s->data, client_s->endp);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(client);
}
static void zclient_mlag_process_up(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
if (zclient->mlag_process_up)
(*zclient->mlag_process_up)();
}
static void zclient_mlag_process_down(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
if (zclient->mlag_process_down)
(*zclient->mlag_process_down)();
}
static void zclient_mlag_handle_msg(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
{
if (zclient->mlag_handle_msg)
(*zclient->mlag_handle_msg)(zclient->ibuf, length);
}
/* Zebra client message read function. */
static int zclient_read(struct thread *thread)
{
@ -3011,6 +3068,15 @@ static int zclient_read(struct thread *thread)
(*zclient->vxlan_sg_del)(command, zclient, length,
vrf_id);
break;
case ZEBRA_MLAG_PROCESS_UP:
zclient_mlag_process_up(command, zclient, length, vrf_id);
break;
case ZEBRA_MLAG_PROCESS_DOWN:
zclient_mlag_process_down(command, zclient, length, vrf_id);
break;
case ZEBRA_MLAG_FORWARD_MSG:
zclient_mlag_handle_msg(command, zclient, length, vrf_id);
break;
default:
break;
}

View File

@ -178,6 +178,11 @@ typedef enum {
ZEBRA_VXLAN_SG_ADD,
ZEBRA_VXLAN_SG_DEL,
ZEBRA_VXLAN_SG_REPLAY,
ZEBRA_MLAG_PROCESS_UP,
ZEBRA_MLAG_PROCESS_DOWN,
ZEBRA_MLAG_CLIENT_REGISTER,
ZEBRA_MLAG_CLIENT_UNREGISTER,
ZEBRA_MLAG_FORWARD_MSG,
} zebra_message_types_t;
struct redist_proto {
@ -272,6 +277,9 @@ struct zclient {
int (*iptable_notify_owner)(ZAPI_CALLBACK_ARGS);
int (*vxlan_sg_add)(ZAPI_CALLBACK_ARGS);
int (*vxlan_sg_del)(ZAPI_CALLBACK_ARGS);
int (*mlag_process_up)(void);
int (*mlag_process_down)(void);
int (*mlag_handle_msg)(struct stream *msg, int len);
};
/* Zebra API message flag. */
@ -693,5 +701,11 @@ static inline void zapi_route_set_blackhole(struct zapi_route *api,
SET_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP);
};
extern void zclient_send_mlag_register(struct zclient *client,
uint32_t bit_map);
extern void zclient_send_mlag_deregister(struct zclient *client);
extern void zclient_send_mlag_data(struct zclient *client,
struct stream *client_s);
#endif /* _ZEBRA_ZCLIENT_H */

186
mlag/mlag.proto Normal file
View File

@ -0,0 +1,186 @@
// See README.txt for information and build instructions.
//
// Note: START and END tags are used in comments to define sections used in
// tutorials. They are not part of the syntax for Protocol Buffers.
//
// To get an in-depth walkthrough of this file and the related examples, see:
// https://developers.google.com/protocol-buffers/docs/tutorials
// [START declaration]
syntax = "proto3";
//package tutorial;
/*
* This Contains the Mesadge structurtes used for PIM MLAG Active-Active support.
* Mainly there were two types of messages
*
* 1. Messages sent from PIM (Node-1) to PIM (Node-2)
* 2. Messages sent from MCLAGD to PIM (status Messages)
*
* ProtoBuf supports maximum 32 fileds, so to make it more generic message
* encoding is like below.
* __________________________________________
* | | |
* | Header | bytes |
* ___________________________________________
*
*
* Header carries Information about
* 1) what Message it is carrying
* 2) Bytes carries teh actual payload encoded with protobuf
*
*
* Limitations
*=============
* Since message-type is 32-bit, there were no real limitations on number of
* messages Infra can support, but each message can carry only 32 fileds.
*
*/
// [START messages]
message ZebraMlag_Header {
enum MessageType {
ZEBRA_MLAG_NONE = 0; //Invalid message-type
ZEBRA_MLAG_REGISTER = 1;
ZEBRA_MLAG_DEREGISTER = 2;
ZEBRA_MLAG_STATUS_UPDATE = 3;
ZEBRA_MLAG_MROUTE_ADD = 4;
ZEBRA_MLAG_MROUTE_DEL = 5;
ZEBRA_MLAG_DUMP = 6;
ZEBRA_MLAG_MROUTE_ADD_BULK = 7;
ZEBRA_MLAG_MROUTE_DEL_BULK = 8;
ZEBRA_MLAG_PIM_CFG_DUMP = 10;
ZEBRA_MLAG_VXLAN_UPDATE = 11;
ZEBRA_MLAG_ZEBRA_STATUS_UPDATE = 12;
}
/*
* tells what type of message this payload carries
*/
MessageType type = 1;
/*
* Length of payload
*/
uint32 len = 2;
/*
* Actual Encoded payload
*/
bytes data = 3;
}
/*
* ZEBRA_MLAG_REGISTER & ZEBRA_MLAG_DEREGISTER
*
* After the MLAGD is up, First Zebra has to register to send any data,
* otherwise MLAGD will not accept any data from the client.
* De-register will be used for the Data cleanup at MLAGD
* These are NULL payload message currently
*/
/*
* ZEBRA_MLAG_STATUS_UPDATE
*
* This message will be posted by CLAGD(an external control plane manager
* which monitors MCLAG failures) to inform peerlink/CLAG Failure
* to zebra, after the failure Notification Node with primary role will
* forward the Traffic and Node with standby will drop the traffic
*/
message ZebraMlagStatusUpdate {
enum ClagState {
CLAG_STATE_DOWN = 0;
CLAG_STATE_RUNNING = 1;
}
enum ClagRole {
CLAG_ROLE_NONE = 0;
CLAG_ROLE_PRIMAY = 1;
CLAG_ROLE_SECONDARY = 2;
}
string peerlink = 1;
ClagRole my_role = 2;
ClagState peer_state = 3;
}
/*
* ZEBRA_MLAG_VXLAN_UPDATE
*
* This message will be posted by CLAGD(an external control plane Manager
* which is responsible for MCLAG) to inform zebra obout anycast/local
* ip updates.
*/
message ZebraMlagVxlanUpdate {
uint32 anycast_ip = 1;
uint32 local_ip = 2;
}
/*
* ZebraMlagZebraStatusUpdate
*
* This message will be posted by CLAGD to advertise FRR state
* Change Information to peer
*/
message ZebraMlagZebraStatusUpdate{
enum FrrState {
FRR_STATE_NONE = 0;
FRR_STATE_DOWN = 1;
FRR_STATE_UP = 2;
}
FrrState peer_frrstate = 1;
}
/*
* ZEBRA_MLAG_MROUTE_ADD & ZEBRA_MLAG_MROUTE_DEL
*
* These meesages will be sent from PIM (Node-1) to PIM (Node-2) to perform
* DF Election for each Mcast flow. Elected DF will forward the tarffic
* towards the host and loser will keep the OIL as empty, sothat only single
* copy will be sent to host
* This message will be posted with any chnage in the params.
*
* ZEBRA_MLAG_MROUTE_DEL is mainly to delete the record at MLAGD when the
* mcast flow is deleted.
* key for the MLAGD lookup is (vrf_id, source_ip & group_ip)
*/
message ZebraMlagMrouteAdd {
string vrf_name = 1;
uint32 source_ip = 2;
uint32 group_ip = 3;
/*
* This is the IGP Cost to reach Configured RP in case of (*,G) or
* Cost to the source in case of (S,G) entry
*/
uint32 cost_to_rp = 4;
uint32 owner_id = 5;
bool am_i_DR = 6;
bool am_i_Dual_active = 7;
uint32 vrf_id = 8;
string intf_name = 9;
}
message ZebraMlagMrouteDel {
string vrf_name = 1;
uint32 source_ip = 2;
uint32 group_ip = 3;
uint32 owner_id = 4;
uint32 vrf_id = 5;
string intf_name = 6;
}
message ZebraMlagMrouteAddBulk {
repeated ZebraMlagMrouteAdd mroute_add = 1;
}
message ZebraMlagMrouteDelBulk {
repeated ZebraMlagMrouteDel mroute_del = 1;
}
// [END messages]

19
mlag/subdir.am Normal file
View File

@ -0,0 +1,19 @@
if HAVE_PROTOBUF
lib_LTLIBRARIES += mlag/libmlag_pb.la
endif
mlag_libmlag_pb_la_LDFLAGS = -version-info 0:0:0
mlag_libmlag_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(PROTOBUF_C_CFLAGS)
mlag_libmlag_pb_la_SOURCES = \
# end
nodist_mlag_libmlag_pb_la_SOURCES = \
mlag/mlag.pb-c.c \
# end
CLEANFILES += \
mlag/mlag.pb-c.c \
mlag/mlag.pb-c.h \
# end
EXTRA_DIST += mlag/mlag.proto

View File

@ -61,6 +61,7 @@
#include "pim_nht.h"
#include "pim_bfd.h"
#include "pim_vxlan.h"
#include "pim_mlag.h"
#include "bfd.h"
#include "pim_bsm.h"
@ -7462,9 +7463,9 @@ DEFPY_HIDDEN (interface_ip_pim_activeactive,
pim_ifp = ifp->info;
if (no)
pim_ifp->activeactive = false;
pim_if_unconfigure_mlag_dualactive(pim_ifp);
else
pim_ifp->activeactive = true;
pim_if_configure_mlag_dualactive(pim_ifp);
return CMD_SUCCESS;
}
@ -8382,6 +8383,20 @@ DEFUN (no_debug_pim_zebra,
return CMD_SUCCESS;
}
DEFUN(debug_pim_mlag, debug_pim_mlag_cmd, "debug pim mlag",
DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
{
PIM_DO_DEBUG_MLAG;
return CMD_SUCCESS;
}
DEFUN(no_debug_pim_mlag, no_debug_pim_mlag_cmd, "no debug pim mlag",
NO_STR DEBUG_STR DEBUG_PIM_STR DEBUG_PIM_MLAG_STR)
{
PIM_DONT_DEBUG_MLAG;
return CMD_SUCCESS;
}
DEFUN (debug_pim_vxlan,
debug_pim_vxlan_cmd,
"debug pim vxlan",
@ -10408,6 +10423,8 @@ void pim_cmd_init(void)
install_element(ENABLE_NODE, &no_debug_ssmpingd_cmd);
install_element(ENABLE_NODE, &debug_pim_zebra_cmd);
install_element(ENABLE_NODE, &no_debug_pim_zebra_cmd);
install_element(ENABLE_NODE, &debug_pim_mlag_cmd);
install_element(ENABLE_NODE, &no_debug_pim_mlag_cmd);
install_element(ENABLE_NODE, &debug_pim_vxlan_cmd);
install_element(ENABLE_NODE, &no_debug_pim_vxlan_cmd);
install_element(ENABLE_NODE, &debug_msdp_cmd);

View File

@ -54,6 +54,7 @@
#define DEBUG_PIM_PACKETDUMP_RECV_STR "Dump received packets\n"
#define DEBUG_PIM_TRACE_STR "PIM internal daemon activity\n"
#define DEBUG_PIM_ZEBRA_STR "ZEBRA protocol activity\n"
#define DEBUG_PIM_MLAG_STR "PIM Mlag activity\n"
#define DEBUG_PIM_VXLAN_STR "PIM VxLAN events\n"
#define DEBUG_SSMPINGD_STR "ssmpingd activity\n"
#define CLEAR_IP_IGMP_STR "IGMP clear commands\n"

View File

@ -34,6 +34,7 @@
#include "pim_ssmpingd.h"
#include "pim_vty.h"
#include "pim_bsm.h"
#include "pim_mlag.h"
static void pim_instance_terminate(struct pim_instance *pim)
{
@ -47,6 +48,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
if (pim->static_routes)
list_delete(&pim->static_routes);
pim_instance_mlag_terminate(pim);
pim_upstream_terminate(pim);
pim_rp_free(pim);
@ -115,6 +118,8 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
pim_upstream_init(pim);
pim_instance_mlag_init(pim);
pim->last_route_change_time = -1;
return pim;
}

View File

@ -64,6 +64,17 @@ struct pim_router {
vrf_id_t vrf_id;
enum mlag_role role;
uint32_t pim_mlag_intf_cnt;
/* if true we have registered with MLAG */
bool mlag_process_register;
/* if true local MLAG process reported that it is connected
* with the peer MLAG process
*/
bool connected_to_mlag;
/* Holds the client data(unencoded) that need to be pushed to MCLAGD*/
struct stream_fifo *mlag_fifo;
struct stream *mlag_stream;
struct thread *zpthread_mlag_write;
};
/* Per VRF PIM DB */
@ -122,6 +133,9 @@ struct pim_instance {
bool ecmp_enable;
bool ecmp_rebalance_enable;
/* No. of Dual active I/fs in pim_instance */
uint32_t inst_mlag_intf_cnt;
/* Bsm related */
struct bsm_scope global_scope;
uint64_t bsm_rcvd;

View File

@ -47,6 +47,7 @@
#include "pim_msdp.h"
#include "pim_iface.h"
#include "pim_bfd.h"
#include "pim_mlag.h"
#include "pim_errors.h"
extern struct host host;
@ -131,6 +132,7 @@ int main(int argc, char **argv, char **envp)
pim_ifp_down, pim_ifp_destroy);
pim_zebra_init();
pim_bfd_init();
pim_mlag_init();
frr_config_fork();

344
pimd/pim_mlag.c Normal file
View File

@ -0,0 +1,344 @@
/* PIM Mlag Code.
* Copyright (C) 2019 Cumulus Networks, Inc.
* Donald Sharp
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <zebra.h>
#include "pimd.h"
#include "pim_mlag.h"
extern struct zclient *zclient;
/********************API to process PIM MLAG Data ************************/
static void pim_mlag_process_mlagd_state_change(struct mlag_status msg)
{
char buf[80];
if (PIM_DEBUG_MLAG)
zlog_debug("%s: msg dump: my_role:%s, peer_state:%s", __func__,
mlag_role2str(msg.my_role, buf, sizeof(buf)),
(msg.peer_state == MLAG_STATE_RUNNING ? "RUNNING"
: "DOWN"));
}
static void pim_mlag_process_peer_frr_state_change(struct mlag_frr_status msg)
{
if (PIM_DEBUG_MLAG)
zlog_debug(
"%s: msg dump: peer_frr_state:%s", __func__,
(msg.frr_state == MLAG_FRR_STATE_UP ? "UP" : "DOWN"));
}
static void pim_mlag_process_vxlan_update(struct mlag_vxlan *msg)
{
}
static void pim_mlag_process_mroute_add(struct mlag_mroute_add msg)
{
if (PIM_DEBUG_MLAG) {
zlog_debug(
"%s: msg dump: vrf_name:%s, s.ip:0x%x, g.ip:0x%x cost:%u",
__func__, msg.vrf_name, msg.source_ip, msg.group_ip,
msg.cost_to_rp);
zlog_debug(
"owner_id:%d, DR:%d, Dual active:%d, vrf_id:0x%x intf_name:%s",
msg.owner_id, msg.am_i_dr, msg.am_i_dual_active,
msg.vrf_id, msg.intf_name);
}
}
static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg)
{
if (PIM_DEBUG_MLAG) {
zlog_debug("%s: msg dump: vrf_name:%s, s.ip:0x%x, g.ip:0x%x ",
__func__, msg.vrf_name, msg.source_ip, msg.group_ip);
zlog_debug("owner_id:%d, vrf_id:0x%x intf_name:%s",
msg.owner_id, msg.vrf_id, msg.intf_name);
}
}
int pim_zebra_mlag_handle_msg(struct stream *s, int len)
{
struct mlag_msg mlag_msg;
char buf[80];
int rc = 0;
rc = zebra_mlag_lib_decode_mlag_hdr(s, &mlag_msg);
if (rc)
return (rc);
if (PIM_DEBUG_MLAG)
zlog_debug(
"%s: Received msg type:%s length:%d, bulk_cnt:%d",
__func__,
zebra_mlag_lib_msgid_to_str(mlag_msg.msg_type, buf, 80),
mlag_msg.data_len, mlag_msg.msg_cnt);
switch (mlag_msg.msg_type) {
case MLAG_STATUS_UPDATE: {
struct mlag_status msg;
rc = zebra_mlag_lib_decode_mlag_status(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mlagd_state_change(msg);
} break;
case MLAG_PEER_FRR_STATUS: {
struct mlag_frr_status msg;
rc = zebra_mlag_lib_decode_frr_status(s, &msg);
if (rc)
return (rc);
pim_mlag_process_peer_frr_state_change(msg);
} break;
case MLAG_VXLAN_UPDATE: {
struct mlag_vxlan msg;
rc = zebra_mlag_lib_decode_vxlan_update(s, &msg);
if (rc)
return rc;
pim_mlag_process_vxlan_update(&msg);
} break;
case MLAG_MROUTE_ADD: {
struct mlag_mroute_add msg;
rc = zebra_mlag_lib_decode_mroute_add(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_add(msg);
} break;
case MLAG_MROUTE_DEL: {
struct mlag_mroute_del msg;
rc = zebra_mlag_lib_decode_mroute_del(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_del(msg);
} break;
case MLAG_MROUTE_ADD_BULK: {
struct mlag_mroute_add msg;
int i = 0;
for (i = 0; i < mlag_msg.msg_cnt; i++) {
rc = zebra_mlag_lib_decode_mroute_add(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_add(msg);
}
} break;
case MLAG_MROUTE_DEL_BULK: {
struct mlag_mroute_del msg;
int i = 0;
for (i = 0; i < mlag_msg.msg_cnt; i++) {
rc = zebra_mlag_lib_decode_mroute_del(s, &msg);
if (rc)
return (rc);
pim_mlag_process_mroute_del(msg);
}
} break;
default:
break;
}
return 0;
}
/****************End of PIM Mesasge processing handler********************/
int pim_zebra_mlag_process_up(void)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Up from Mlag", __func__);
return 0;
}
int pim_zebra_mlag_process_down(void)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Down from Mlag", __func__);
return 0;
}
static int pim_mlag_register_handler(struct thread *thread)
{
uint32_t bit_mask = 0;
if (!zclient)
return -1;
SET_FLAG(bit_mask, (1 << MLAG_STATUS_UPDATE));
SET_FLAG(bit_mask, (1 << MLAG_MROUTE_ADD));
SET_FLAG(bit_mask, (1 << MLAG_MROUTE_DEL));
SET_FLAG(bit_mask, (1 << MLAG_DUMP));
SET_FLAG(bit_mask, (1 << MLAG_MROUTE_ADD_BULK));
SET_FLAG(bit_mask, (1 << MLAG_MROUTE_DEL_BULK));
SET_FLAG(bit_mask, (1 << MLAG_PIM_CFG_DUMP));
SET_FLAG(bit_mask, (1 << MLAG_VXLAN_UPDATE));
SET_FLAG(bit_mask, (1 << MLAG_PEER_FRR_STATUS));
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Posting Client Register to MLAG mask:0x%x",
__func__, bit_mask);
zclient_send_mlag_register(zclient, bit_mask);
return 0;
}
void pim_mlag_register(void)
{
if (router->mlag_process_register)
return;
router->mlag_process_register = true;
thread_add_event(router->master, pim_mlag_register_handler, NULL, 0,
NULL);
}
static int pim_mlag_deregister_handler(struct thread *thread)
{
if (!zclient)
return -1;
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Posting Client De-Register to MLAG from PIM",
__func__);
router->connected_to_mlag = false;
zclient_send_mlag_deregister(zclient);
return 0;
}
void pim_mlag_deregister(void)
{
/* if somebody still interested in the MLAG channel skip de-reg */
if (router->pim_mlag_intf_cnt)
return;
/* not registered; nothing do */
if (!router->mlag_process_register)
return;
router->mlag_process_register = false;
thread_add_event(router->master, pim_mlag_deregister_handler, NULL, 0,
NULL);
}
void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp)
{
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == true)
return;
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Configuring active-active on Interface: %s",
__func__, "NULL");
pim_ifp->activeactive = true;
if (pim_ifp->pim)
pim_ifp->pim->inst_mlag_intf_cnt++;
router->pim_mlag_intf_cnt++;
if (PIM_DEBUG_MLAG)
zlog_debug(
"%s: Total MLAG configured Interfaces on router: %d, Inst:%d",
__func__, router->pim_mlag_intf_cnt,
pim_ifp->pim->inst_mlag_intf_cnt);
if (router->pim_mlag_intf_cnt == 1) {
/*
* atleast one Interface is configured for MLAG, send register
* to Zebra for receiving MLAG Updates
*/
pim_mlag_register();
}
}
void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp)
{
if (!pim_ifp || !pim_ifp->pim || pim_ifp->activeactive == false)
return;
if (PIM_DEBUG_MLAG)
zlog_debug("%s: UnConfiguring active-active on Interface: %s",
__func__, "NULL");
pim_ifp->activeactive = false;
if (pim_ifp->pim)
pim_ifp->pim->inst_mlag_intf_cnt--;
router->pim_mlag_intf_cnt--;
if (PIM_DEBUG_MLAG)
zlog_debug(
"%s: Total MLAG configured Interfaces on router: %d, Inst:%d",
__func__, router->pim_mlag_intf_cnt,
pim_ifp->pim->inst_mlag_intf_cnt);
if (router->pim_mlag_intf_cnt == 0) {
/*
* all the Interfaces are MLAG un-configured, post MLAG
* De-register to Zebra
*/
pim_mlag_deregister();
}
}
void pim_instance_mlag_init(struct pim_instance *pim)
{
if (!pim)
return;
pim->inst_mlag_intf_cnt = 0;
}
void pim_instance_mlag_terminate(struct pim_instance *pim)
{
struct interface *ifp;
if (!pim)
return;
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp = ifp->info;
if (!pim_ifp || pim_ifp->activeactive == false)
continue;
pim_if_unconfigure_mlag_dualactive(pim_ifp);
}
pim->inst_mlag_intf_cnt = 0;
}
void pim_mlag_init(void)
{
router->pim_mlag_intf_cnt = 0;
router->connected_to_mlag = false;
router->mlag_fifo = stream_fifo_new();
router->zpthread_mlag_write = NULL;
router->mlag_stream = stream_new(MLAG_BUF_LIMIT);
}

48
pimd/pim_mlag.h Normal file
View File

@ -0,0 +1,48 @@
/* PIM mlag header.
* Copyright (C) 2019 Cumulus Networks, Inc.
* Donald Sharp
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __PIM_MLAG_H__
#define __PIM_MLAG_H__
#include "mlag.h"
#include "pim_iface.h"
extern void pim_mlag_init(void);
extern void pim_instance_mlag_init(struct pim_instance *pim);
extern void pim_instance_mlag_terminate(struct pim_instance *pim);
extern void pim_if_configure_mlag_dualactive(struct pim_interface *pim_ifp);
extern void pim_if_unconfigure_mlag_dualactive(struct pim_interface *pim_ifp);
extern void pim_mlag_register(void);
extern void pim_mlag_deregister(void);
extern int pim_zebra_mlag_process_up(void);
extern int pim_zebra_mlag_process_down(void);
extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
#endif

View File

@ -46,11 +46,12 @@
#include "pim_nht.h"
#include "pim_ssm.h"
#include "pim_vxlan.h"
#include "pim_mlag.h"
#undef PIM_DEBUG_IFADDR_DUMP
#define PIM_DEBUG_IFADDR_DUMP
static struct zclient *zclient = NULL;
struct zclient *zclient;
/* Router-id update message from zebra. */
@ -587,6 +588,9 @@ void pim_zebra_init(void)
zclient->nexthop_update = pim_parse_nexthop_update;
zclient->vxlan_sg_add = pim_zebra_vxlan_sg_proc;
zclient->vxlan_sg_del = pim_zebra_vxlan_sg_proc;
zclient->mlag_process_up = pim_zebra_mlag_process_up;
zclient->mlag_process_down = pim_zebra_mlag_process_down;
zclient->mlag_handle_msg = pim_zebra_mlag_handle_msg;
zclient_init(zclient, ZEBRA_ROUTE_PIM, 0, &pimd_privs);
if (PIM_DEBUG_PIM_TRACE) {

View File

@ -115,6 +115,7 @@
#define PIM_MASK_MTRACE (1 << 25)
#define PIM_MASK_VXLAN (1 << 26)
#define PIM_MASK_BSM_PROC (1 << 27)
#define PIM_MASK_MLAG (1 << 28)
/* Remember 32 bits!!! */
/* PIM error codes */
@ -171,6 +172,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DEBUG_IGMP_TRACE_DETAIL \
(router->debugs & (PIM_MASK_IGMP_TRACE_DETAIL | PIM_MASK_IGMP_TRACE))
#define PIM_DEBUG_ZEBRA (router->debugs & PIM_MASK_ZEBRA)
#define PIM_DEBUG_MLAG (router->debugs & PIM_MASK_MLAG)
#define PIM_DEBUG_SSMPINGD (router->debugs & PIM_MASK_SSMPINGD)
#define PIM_DEBUG_MROUTE (router->debugs & PIM_MASK_MROUTE)
#define PIM_DEBUG_MROUTE_DETAIL \
@ -217,6 +219,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DO_DEBUG_IGMP_TRACE_DETAIL \
(router->debugs |= PIM_MASK_IGMP_TRACE_DETAIL)
#define PIM_DO_DEBUG_ZEBRA (router->debugs |= PIM_MASK_ZEBRA)
#define PIM_DO_DEBUG_MLAG (router->debugs |= PIM_MASK_MLAG)
#define PIM_DO_DEBUG_SSMPINGD (router->debugs |= PIM_MASK_SSMPINGD)
#define PIM_DO_DEBUG_MROUTE (router->debugs |= PIM_MASK_MROUTE)
#define PIM_DO_DEBUG_MROUTE_DETAIL (router->debugs |= PIM_MASK_MROUTE_DETAIL)
@ -248,6 +251,7 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DONT_DEBUG_IGMP_TRACE_DETAIL \
(router->debugs &= ~PIM_MASK_IGMP_TRACE_DETAIL)
#define PIM_DONT_DEBUG_ZEBRA (router->debugs &= ~PIM_MASK_ZEBRA)
#define PIM_DONT_DEBUG_MLAG (router->debugs &= ~PIM_MASK_MLAG)
#define PIM_DONT_DEBUG_SSMPINGD (router->debugs &= ~PIM_MASK_SSMPINGD)
#define PIM_DONT_DEBUG_MROUTE (router->debugs &= ~PIM_MASK_MROUTE)
#define PIM_DONT_DEBUG_MROUTE_DETAIL (router->debugs &= ~PIM_MASK_MROUTE_DETAIL)

View File

@ -62,6 +62,7 @@ pimd_libpim_a_SOURCES = \
pimd/pim_zebra.c \
pimd/pim_zlookup.c \
pimd/pim_vxlan.c \
pimd/pim_mlag.c \
pimd/pimd.c \
# end
@ -114,6 +115,7 @@ noinst_HEADERS += \
pimd/pim_zebra.h \
pimd/pim_zlookup.h \
pimd/pim_vxlan.h \
pimd/pim_mlag.h \
pimd/pim_vxlan_instance.h \
pimd/pimd.h \
pimd/mtracebis_netlink.h \

View File

@ -38,6 +38,9 @@ man8 += $(MANBUILD)/zebra.8
endif
zebra_zebra_LDADD = lib/libfrr.la $(LIBCAP)
if HAVE_PROTOBUF
zebra_zebra_LDADD += mlag/libmlag_pb.la $(PROTOBUF_C_LIBS)
endif
zebra_zebra_SOURCES = \
zebra/connected.c \
zebra/debug.c \
@ -66,6 +69,7 @@ zebra_zebra_SOURCES = \
zebra/rule_netlink.c \
zebra/rule_socket.c \
zebra/zebra_mlag.c \
zebra/zebra_mlag_private.c \
zebra/zebra_l2.c \
zebra/zebra_memory.c \
zebra/zebra_dplane.c \
@ -130,6 +134,7 @@ noinst_HEADERS += \
zebra/rtadv.h \
zebra/rule_netlink.h \
zebra/zebra_mlag.h \
zebra/zebra_mlag_private.h \
zebra/zebra_fpm_private.h \
zebra/zebra_l2.h \
zebra/zebra_dplane.h \

View File

@ -2551,6 +2551,9 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_IPTABLE_DELETE] = zread_iptable,
[ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control,
[ZEBRA_VXLAN_SG_REPLAY] = zebra_vxlan_sg_replay,
[ZEBRA_MLAG_CLIENT_REGISTER] = zebra_mlag_client_register,
[ZEBRA_MLAG_CLIENT_UNREGISTER] = zebra_mlag_client_unregister,
[ZEBRA_MLAG_FORWARD_MSG] = zebra_mlag_forward_client_msg,
};
#if defined(HANDLE_ZAPI_FUZZING)

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* Zebra mlag header.
* Copyright (C) 2018 Cumulus Networks, Inc.
* Copyright (C) 2019 Cumulus Networks, Inc.
* Donald Sharp
*
* This file is part of FRR.
@ -23,18 +23,55 @@
#define __ZEBRA_MLAG_H__
#include "mlag.h"
#include "zclient.h"
#include "zebra/zserv.h"
#ifdef __cplusplus
extern "C" {
#ifdef HAVE_PROTOBUF
#include "mlag/mlag.pb-c.h"
#endif
#define ZEBRA_MLAG_BUF_LIMIT 2048
#define ZEBRA_MLAG_LEN_SIZE 4
extern uint8_t mlag_wr_buffer[ZEBRA_MLAG_BUF_LIMIT];
extern uint8_t mlag_rd_buffer[ZEBRA_MLAG_BUF_LIMIT];
extern uint32_t mlag_rd_buf_offset;
static inline void zebra_mlag_reset_read_buffer(void)
{
mlag_rd_buf_offset = 0;
}
enum zebra_mlag_state {
MLAG_UP = 1,
MLAG_DOWN = 2,
};
void zebra_mlag_init(void);
void zebra_mlag_terminate(void);
enum mlag_role zebra_mlag_get_role(void);
#ifdef __cplusplus
}
#endif
void zebra_mlag_client_register(ZAPI_HANDLER_ARGS);
void zebra_mlag_client_unregister(ZAPI_HANDLER_ARGS);
void zebra_mlag_forward_client_msg(ZAPI_HANDLER_ARGS);
void zebra_mlag_send_register(void);
void zebra_mlag_send_deregister(void);
void zebra_mlag_handle_process_state(enum zebra_mlag_state state);
void zebra_mlag_process_mlag_data(uint8_t *data, uint32_t len);
/*
* ProtoBuffer Api's
*/
int zebra_mlag_protobuf_encode_client_data(struct stream *s,
uint32_t *msg_type);
int zebra_mlag_protobuf_decode_message(struct stream **s, uint8_t *data,
uint32_t len);
#endif

302
zebra/zebra_mlag_private.c Normal file
View File

@ -0,0 +1,302 @@
/* Zebra Mlag Code.
* Copyright (C) 2019 Cumulus Networks, Inc.
* Donald Sharp
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "zebra.h"
#include "hook.h"
#include "module.h"
#include "thread.h"
#include "libfrr.h"
#include "version.h"
#include "network.h"
#include "lib/stream.h"
#include "zebra/debug.h"
#include "zebra/zebra_router.h"
#include "zebra/zebra_mlag.h"
#include "zebra/zebra_mlag_private.h"
#include <sys/un.h>
/*
* This file will have platform specific apis to communicate with MCLAG.
*
*/
#ifdef HAVE_CUMULUS
static struct thread_master *zmlag_master;
static int mlag_socket;
static int zebra_mlag_connect(struct thread *thread);
static int zebra_mlag_read(struct thread *thread);
/*
* Write teh data to MLAGD
*/
int zebra_mlag_private_write_data(uint8_t *data, uint32_t len)
{
int rc = 0;
if (IS_ZEBRA_DEBUG_MLAG) {
zlog_debug("%s: Writing %d length Data to clag", __func__, len);
zlog_hexdump(data, len);
}
rc = write(mlag_socket, data, len);
return rc;
}
static void zebra_mlag_sched_read(void)
{
pthread_mutex_lock(&zrouter.mlag_info.mlag_th_mtx);
thread_add_read(zmlag_master, zebra_mlag_read, NULL, mlag_socket,
&zrouter.mlag_info.t_read);
pthread_mutex_unlock(&zrouter.mlag_info.mlag_th_mtx);
}
static int zebra_mlag_read(struct thread *thread)
{
uint32_t *msglen;
uint32_t h_msglen;
uint32_t tot_len, curr_len = mlag_rd_buf_offset;
pthread_mutex_lock(&zrouter.mlag_info.mlag_th_mtx);
zrouter.mlag_info.t_read = NULL;
pthread_mutex_unlock(&zrouter.mlag_info.mlag_th_mtx);
/*
* Received message in sock_stream looks like below
* | len-1 (4 Bytes) | payload-1 (len-1) |
* len-2 (4 Bytes) | payload-2 (len-2) | ..
*
* Idea is read one message completely, then process, until message is
* read completely, keep on reading from the socket
*/
if (curr_len < ZEBRA_MLAG_LEN_SIZE) {
ssize_t data_len;
data_len = read(mlag_socket, mlag_rd_buffer + curr_len,
ZEBRA_MLAG_LEN_SIZE - curr_len);
if (data_len == 0 || data_len == -1) {
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug("MLAG connection closed socket : %d",
mlag_socket);
close(mlag_socket);
zebra_mlag_handle_process_state(MLAG_DOWN);
return -1;
}
if (data_len != (ssize_t)ZEBRA_MLAG_LEN_SIZE - curr_len) {
/* Try again later */
zebra_mlag_sched_read();
return 0;
}
curr_len = ZEBRA_MLAG_LEN_SIZE;
}
/* Get the actual packet length */
msglen = (uint32_t *)mlag_rd_buffer;
h_msglen = ntohl(*msglen);
/* This will be the actual length of the packet */
tot_len = h_msglen + ZEBRA_MLAG_LEN_SIZE;
if (curr_len < tot_len) {
ssize_t data_len;
data_len = read(mlag_socket, mlag_rd_buffer + curr_len,
tot_len - curr_len);
if (data_len == 0 || data_len == -1) {
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug("MLAG connection closed socket : %d",
mlag_socket);
close(mlag_socket);
zebra_mlag_handle_process_state(MLAG_DOWN);
return -1;
}
if (data_len != (ssize_t)tot_len - curr_len) {
/* Try again later */
zebra_mlag_sched_read();
return 0;
}
}
if (IS_ZEBRA_DEBUG_MLAG) {
zlog_debug("Received a MLAG Message from socket: %d, len:%u ",
mlag_socket, tot_len);
zlog_hexdump(mlag_rd_buffer, tot_len);
}
tot_len -= ZEBRA_MLAG_LEN_SIZE;
/* Process the packet */
zebra_mlag_process_mlag_data(mlag_rd_buffer + ZEBRA_MLAG_LEN_SIZE,
tot_len);
/* Register read thread. */
zebra_mlag_reset_read_buffer();
zebra_mlag_sched_read();
return 0;
}
static int zebra_mlag_connect(struct thread *thread)
{
struct sockaddr_un svr;
struct ucred ucred;
socklen_t len = 0;
/* Reset the Timer-running flag */
zrouter.mlag_info.timer_running = false;
zrouter.mlag_info.t_read = NULL;
memset(&svr, 0, sizeof(svr));
svr.sun_family = AF_UNIX;
#define MLAG_SOCK_NAME "/var/run/clag-zebra.socket"
strlcpy(svr.sun_path, MLAG_SOCK_NAME, sizeof(MLAG_SOCK_NAME) + 1);
mlag_socket = socket(svr.sun_family, SOCK_STREAM, 0);
if (mlag_socket < 0)
return -1;
if (connect(mlag_socket, (struct sockaddr *)&svr, sizeof(svr)) == -1) {
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug(
"Unable to connect to %s try again in 10 secs",
svr.sun_path);
close(mlag_socket);
zrouter.mlag_info.timer_running = true;
thread_add_timer(zmlag_master, zebra_mlag_connect, NULL, 10,
&zrouter.mlag_info.t_read);
return 0;
}
len = sizeof(struct ucred);
ucred.pid = getpid();
set_nonblocking(mlag_socket);
setsockopt(mlag_socket, SOL_SOCKET, SO_PEERCRED, &ucred, len);
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug("%s: Connection with MLAG is established ",
__func__);
thread_add_read(zmlag_master, zebra_mlag_read, NULL, mlag_socket,
&zrouter.mlag_info.t_read);
/*
* Connection is established with MLAGD, post to clients
*/
zebra_mlag_handle_process_state(MLAG_UP);
return 0;
}
/*
* Currently we are doing polling later we will look for better options
*/
void zebra_mlag_private_monitor_state(void)
{
thread_add_event(zmlag_master, zebra_mlag_connect, NULL, 0,
&zrouter.mlag_info.t_read);
}
int zebra_mlag_private_open_channel(void)
{
zmlag_master = zrouter.mlag_info.th_master;
if (zrouter.mlag_info.connected == true) {
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug("%s: Zebra already connected to MLAGD",
__func__);
return 0;
}
if (zrouter.mlag_info.timer_running == true) {
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug(
"%s: Connection retry is in progress for MLAGD",
__func__);
return 0;
}
if (zrouter.mlag_info.clients_interested_cnt) {
/*
* Connect only if any clients are showing interest
*/
thread_add_event(zmlag_master, zebra_mlag_connect, NULL, 0,
&zrouter.mlag_info.t_read);
}
return 0;
}
int zebra_mlag_private_close_channel(void)
{
if (zmlag_master == NULL)
return -1;
if (zrouter.mlag_info.clients_interested_cnt) {
if (IS_ZEBRA_DEBUG_MLAG)
zlog_debug("%s: still %d clients are connected, skip",
__func__,
zrouter.mlag_info.clients_interested_cnt);
return -1;
}
/*
* Post the De-register to MLAG, so that it can do necesasry cleanup
*/
zebra_mlag_send_deregister();
return 0;
}
void zebra_mlag_private_cleanup_data(void)
{
zmlag_master = NULL;
zrouter.mlag_info.connected = false;
zrouter.mlag_info.timer_running = false;
close(mlag_socket);
}
#else /*HAVE_CUMULUS */
int zebra_mlag_private_write_data(uint8_t *data, uint32_t len)
{
return 0;
}
void zebra_mlag_private_monitor_state(void)
{
}
int zebra_mlag_private_open_channel(void)
{
return 0;
}
int zebra_mlag_private_close_channel(void)
{
return 0;
}
void zebra_mlag_private_cleanup_data(void)
{
}
#endif /*HAVE_CUMULUS*/

View File

@ -0,0 +1,40 @@
/* Zebra mlag header.
* Copyright (C) 2019 Cumulus Networks, Inc.
* Donald Sharp
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __ZEBRA_MLAG_PRIVATE_H__
#define __ZEBRA_MLAG_PRIVATE_H__
/*
* all the platform specific API's
*/
int zebra_mlag_private_open_channel(void);
int zebra_mlag_private_close_channel(void);
void zebra_mlag_private_monitor_state(void);
int zebra_mlag_private_write_data(uint8_t *data, uint32_t len);
void zebra_mlag_private_cleanup_data(void);
#endif

View File

@ -71,6 +71,36 @@ struct zebra_mlag_info {
/* The system mac being used */
struct ethaddr mac;
/*
* Zebra will open the communication channel with MLAGD only if any
* clients are interested and it is controlled dynamically based on
* client registers & un-registers.
*/
uint32_t clients_interested_cnt;
/* coomunication channel with MLAGD is established */
bool connected;
/* connection retry timer is running */
bool timer_running;
/* Holds the client data(unencoded) that need to be pushed to MCLAGD*/
struct stream_fifo *mlag_fifo;
/*
* A new Kernel thread will be created to post the data to MCLAGD.
* where as, read will be performed from the zebra main thread, because
* read involves accessing client registartion data structures.
*/
struct frr_pthread *zebra_pth_mlag;
/* MLAG Thread context 'master' */
struct thread_master *th_master;
/* Threads for read/write. */
struct thread *t_read;
struct thread *t_write;
pthread_mutex_t mlag_th_mtx;
};
struct zebra_router {

View File

@ -99,6 +99,13 @@ struct zserv {
uint8_t proto;
uint16_t instance;
/*
* Interested for MLAG Updates, and also stores the client
* interested message mask
*/
bool mlag_updates_interested;
uint32_t mlag_reg_mask1;
/* Statistics */
uint32_t redist_v4_add_cnt;
uint32_t redist_v4_del_cnt;