MCLAG enhacements ICCPd initial code commit (#4819)

* MCLAG enhacements ICCPd initial code commit
* Resolving the merge conflicts with orighin
* L3 MCLAG Enhancements and Unique IP Changes.
* Addressed review comments

Co-authored-by: Tapash Das <tapash.das@broadcom.com>
This commit is contained in:
Praveen-Brcm 2021-08-03 17:32:50 -07:00 committed by Judy Joseph
parent debe310c66
commit 44a2cd8b1a
38 changed files with 8353 additions and 1241 deletions

View File

@ -64,4 +64,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel(const char* ifname);
int set_local_system_id(const char *mac);
int unset_local_system_id();
int set_keepalive_time(int mid, int keepalive_time);
int set_session_timeout(int mid, int session_timeout_val);
#endif

View File

@ -26,4 +26,7 @@
int iccp_config_from_file(char *config_default_dir);
int set_mc_lag_by_id(uint16_t mid);
int unset_mc_lag_by_id(uint16_t mid);
#endif /* ICCP_CMD_H_ */

View File

@ -33,4 +33,6 @@ extern int iccp_ndisc_dump(char * *buf, int *num, int mclag_id);
extern int iccp_mac_dump(char * *buf, int *num, int mclag_id);
extern int iccp_local_if_dump(char * *buf, int *num, int mclag_id);
extern int iccp_peer_if_dump(char * *buf, int *num, int mclag_id);
extern int iccp_cmd_dbg_counter_dump(char * *buf, int *data_len, int mclag_id);
extern int iccp_unique_ip_if_dump(char * *buf, int *num, int mclag_id);
#endif

View File

@ -113,10 +113,15 @@ struct CSM
time_t peer_warm_reboot_time;
time_t warm_reboot_disconn_time;
char peer_itf_name[IFNAMSIZ];
time_t peer_link_learning_retry_time;
char peer_ip[INET_ADDRSTRLEN];
char sender_ip[INET_ADDRSTRLEN];
void* sock_read_event_ptr;
int keepalive_time;
int session_timeout;
int peer_link_learning_enable;
/* Msg queue */
TAILQ_HEAD(msg_list, Msg) msg_list;
@ -164,5 +169,5 @@ void iccp_csm_correspond_from_rg_connect_msg(struct CSM*, struct Msg*);
void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM*, struct Msg*);
int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname);
int iccp_csm_init_mac_msg(struct MACMsg **mac_msg, char* data, int len);
#endif /* ICCP_CSM_H_ */

View File

@ -37,6 +37,8 @@ int do_one_neigh_request(struct nlmsghdr *n);
void iccp_from_netlink_port_state_handler( char * ifname, int state);
void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n);
void vlan_mbrship_change_handler(unsigned int vlan_id, char *mbr_if_name, int add_flag);
void del_all_pending_vlan_mbr_ifs(struct System *sys);
void move_pending_vlan_mbr_to_lif(struct System *sys, struct LocalInterface* lif);
#endif // LACP_IFM_H

View File

@ -26,9 +26,7 @@
#include <stdarg.h>
#include <unistd.h>
#include <netlink/netlink.h>
#include <linux/types.h>
#include "../include/system.h"
#include "../include/port.h"
#include <netinet/icmp6.h>
@ -37,6 +35,7 @@
#define NDISC_NEIGHBOUR_ADVERTISEMENT 136
#define ND_OPT_TARGET_LL_ADDR 2
#define NEXTHDR_ICMP 58
#define ICCP_NLE_SEQ_MISMATCH -16
struct nd_msg
{
@ -58,10 +57,13 @@ int iccp_system_init_netlink_socket();
void iccp_system_dinit_netlink_socket();
int iccp_init_netlink_event_fd(struct System *sys);
int iccp_handle_events(struct System *sys);
void update_if_ipmac_on_standby(struct LocalInterface* lif_po);
void update_if_ipmac_on_standby(struct LocalInterface *lif_po, int dir);
int iccp_sys_local_if_list_get_addr();
int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname);
int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname, int permanent, int dir);
int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif);
void recover_if_ipmac_on_standby(struct LocalInterface* lif_po, int dir);
void update_vlan_if_mac_on_standby(struct LocalInterface* lif_vlan, int dir);
void recover_vlan_if_mac_on_standby(struct LocalInterface* lif_vlan, int dir, uint8_t *remote_system_mac);
void update_vlan_if_mac_on_iccp_up(struct LocalInterface* lif_peer, int is_up, uint8_t *remote_system_mac);
#endif

View File

@ -26,9 +26,12 @@
#define _MLACP_FSM_H
#include "../include/port.h"
#include "../include/mlacp_tlv.h"
#define MLCAP_SYNC_PHY_DEV_SEC 1 /*every 1 sec*/
#define MLACP_LOCAL_IF_DOWN_TIMER 600 // 600 seconds.
#define MLACP(csm_ptr) (csm_ptr->app_csm.mlacp)
struct CSM;
@ -66,6 +69,85 @@ struct Remote_System
uint32_t node_id;
};
/****************************************************************
* Debug counters to track message sent and received between
* MC-LAG peers over ICCP
***************************************************************/
typedef uint8_t ICCP_DBG_CNTR_DIR_e;
enum ICCP_DBG_CNTR_DIR_e
{
ICCP_DBG_CNTR_DIR_TX = 0,
ICCP_DBG_CNTR_DIR_RX = 1,
ICCP_DBG_CNTR_DIR_MAX
};
typedef uint8_t ICCP_DBG_CNTR_STS_e;
enum ICCP_DBG_CNTR_STS_e
{
ICCP_DBG_CNTR_STS_OK = 0,
ICCP_DBG_CNTR_STS_ERR = 1, /* Send error or receive processing error*/
ICCP_DBG_CNTR_STS_MAX
};
/* Change MCLAGDCTL_MAX_DBG_COUNTERS if ICCP_DBG_CNTR_MSG_MAX is more than 32 */
enum ICCP_DBG_CNTR_MSG
{
ICCP_DBG_CNTR_MSG_SYS_CONFIG = 0,
ICCP_DBG_CNTR_MSG_AGGR_CONFIG = 1,
ICCP_DBG_CNTR_MSG_AGGR_STATE = 2,
ICCP_DBG_CNTR_MSG_MAC_INFO = 3,
ICCP_DBG_CNTR_MSG_ARP_INFO = 4,
ICCP_DBG_CNTR_MSG_L2MC_INFO = 5,
ICCP_DBG_CNTR_MSG_PORTCHANNEL_INFO = 6,
ICCP_DBG_CNTR_MSG_PEER_LINK_INFO = 7,
ICCP_DBG_CNTR_MSG_HEART_BEAT = 8,
ICCP_DBG_CNTR_MSG_NAK = 9,
ICCP_DBG_CNTR_MSG_SYNC_DATA = 10,
ICCP_DBG_CNTR_MSG_SYNC_REQ = 11,
ICCP_DBG_CNTR_MSG_WARM_BOOT = 12,
ICCP_DBG_CNTR_MSG_IF_UP_ACK = 13,
ICCP_DBG_CNTR_MSG_STP_CONNECT = 14,
ICCP_DBG_CNTR_MSG_STP_DISCONNECT = 15,
ICCP_DBG_CNTR_MSG_STP_SYSTEM_CONFIG = 16,
ICCP_DBG_CNTR_MSG_STP_REGION_NAME = 17,
ICCP_DBG_CNTR_MSG_STP_REVISION_LEVEL = 18,
ICCP_DBG_CNTR_MSG_STP_INSTANCE_PRIORITY = 19,
ICCP_DBG_CNTR_MSG_STP_CONFIGURATION_DIGEST = 20,
ICCP_DBG_CNTR_MSG_STP_TC_INSTANCES = 21,
ICCP_DBG_CNTR_MSG_STP_ROOT_TIME_PARAM = 22,
ICCP_DBG_CNTR_MSG_STP_MIST_ROOT_TIME_PARAM = 23,
ICCP_DBG_CNTR_MSG_STP_SYNC_REQ = 24,
ICCP_DBG_CNTR_MSG_STP_SYNC_DATA = 25,
ICCP_DBG_CNTR_MSG_STP_PO_PORT_MAP = 26,
ICCP_DBG_CNTR_MSG_STP_AGE_OUT = 27,
ICCP_DBG_CNTR_MSG_STP_COMMON_MSG = 28,
ICCP_DBG_CNTR_MSG_MAX
};
typedef enum ICCP_DBG_CNTR_MSG ICCP_DBG_CNTR_MSG_e;
/* Count messages sent to MCLAG peer */
#define MLACP_SET_ICCP_TX_DBG_COUNTER(csm, tlv_type, status)\
do{\
ICCP_DBG_CNTR_MSG_e dbg_type;\
dbg_type = mlacp_fsm_iccp_to_dbg_msg_type(tlv_type);\
if (csm && ((dbg_type) < ICCP_DBG_CNTR_MSG_MAX) && ((status) < ICCP_DBG_CNTR_STS_MAX))\
++MLACP(csm).dbg_counters.iccp_counters[dbg_type][ICCP_DBG_CNTR_DIR_TX][status];\
}while(0);
/* Count messages received from MCLAG peer */
#define MLACP_SET_ICCP_RX_DBG_COUNTER(csm, tlv_type, status)\
do{\
ICCP_DBG_CNTR_MSG_e dbg_type;\
dbg_type = mlacp_fsm_iccp_to_dbg_msg_type(tlv_type);\
if (csm && ((dbg_type) < ICCP_DBG_CNTR_MSG_MAX) && ((status) < ICCP_DBG_CNTR_STS_MAX))\
++MLACP(csm).dbg_counters.iccp_counters[dbg_type][ICCP_DBG_CNTR_DIR_RX][status];\
}while(0);
typedef struct mlacp_dbg_counter_info
{
uint64_t iccp_counters[ICCP_DBG_CNTR_MSG_MAX][ICCP_DBG_CNTR_DIR_MAX][ICCP_DBG_CNTR_STS_MAX];
}mlacp_dbg_counter_info_t;
struct mLACP
{
int id;
@ -88,12 +170,16 @@ struct mLACP
TAILQ_HEAD(arp_info_list, Msg) arp_list;
TAILQ_HEAD(ndisc_msg_list, Msg) ndisc_msg_list;
TAILQ_HEAD(ndisc_info_list, Msg) ndisc_list;
TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list;
TAILQ_HEAD(mac_info_list, Msg) mac_list;
TAILQ_HEAD(mac_msg_list, MACMsg) mac_msg_list;
struct mac_rb_tree mac_rb;
LIST_HEAD(lif_list, LocalInterface) lif_list;
LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list;
LIST_HEAD(pif_list, PeerInterface) pif_list;
/* ICCP message tx/rx debug counters */
mlacp_dbg_counter_info_t dbg_counters;
};
void mlacp_init(struct CSM* csm, int all);
@ -101,9 +187,13 @@ void mlacp_finalize(struct CSM* csm);
void mlacp_fsm_transit(struct CSM* csm);
void mlacp_enqueue_msg(struct CSM*, struct Msg*);
struct Msg* mlacp_dequeue_msg(struct CSM*);
char* mlacp_state(struct CSM* csm);
/* from app_csm*/
extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if);
extern int mlacp_unbind_local_if(struct LocalInterface* local_if);
/* Debug counter API */
ICCP_DBG_CNTR_MSG_e mlacp_fsm_iccp_to_dbg_msg_type(uint32_t tlv_type);
#endif /* _MLACP_HANDLER_H */

View File

@ -23,9 +23,16 @@
#ifndef __MLACP_LINK_HANDLER__
#define __MLACP_LINK_HANDLER__
#include <stdbool.h>
#include "../include/iccp_csm.h"
#include "../include/mlacp_tlv.h"
#define MCLAG_MAX_MSG_LEN 4096
#define ICCP_MLAGSYNCD_SEND_MSG_BUFFER_SIZE MCLAG_MAX_MSG_LEN
#define ICCP_MLAGSYNCD_RECV_MSG_BUFFER_SIZE (MCLAG_MAX_MSG_LEN * 256)
extern char g_iccp_recv_buf[];
/*****************************************
* Link Handler
*
@ -43,18 +50,48 @@ void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable);
void peerlink_port_isolate_cleanup(struct CSM* csm);
void update_peerlink_isolate_from_all_csm_lif(struct CSM* csm);
ssize_t iccp_send_to_mclagsyncd(uint8_t msg_type, char *send_buff, uint16_t send_len);
void del_mac_from_chip(struct MACMsg* mac_msg);
void add_mac_to_chip(struct MACMsg* mac_msg, uint8_t mac_type);
uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg *mac_msg, uint8_t set);
void iccp_get_fdb_change_from_syncd(void);
uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t set, uint8_t update_peer);
extern int mclagd_ctl_sock_create();
extern int mclagd_ctl_sock_accept(int fd);
extern int mclagd_ctl_interactive_process(int client_fd);
extern int parseMacString(const char *str_mac, uint8_t *bin_mac);
char *show_ip_str(uint32_t ipv4_addr);
char *show_ipv6_str(char *ipv6_addr);
void syncd_info_close();
int iccp_connect_syncd();
void mlacp_link_disable_traffic_distribution(struct LocalInterface *lif);
void mlacp_link_enable_traffic_distribution(struct LocalInterface *lif);
int mlacp_link_set_iccp_state(int mlag_id, bool is_oper_up);
int mlacp_link_set_iccp_role(int mlag_id, bool is_active_role, uint8_t *system_id);
int mlacp_link_set_iccp_system_id(int mlag_id, uint8_t *system_id);
int mlacp_link_del_iccp_info(int mlag_id);
int mlacp_link_set_remote_if_state(int mlag_id, char *po_name, bool is_oper_up);
int mlacp_link_del_remote_if_info(int mlag_id, char *po_name);
int mlacp_link_set_peerlink_port_isolation(int mlag_id, char *po_name, bool is_isolation_enable);
void mlacp_mlag_intf_detach_handler(struct CSM* csm, struct LocalInterface* local_if);
void mlacp_peer_mlag_intf_delete_handler(struct CSM* csm, char *mlag_if_name);
int iccp_mclagsyncd_msg_handler(struct System *sys);
int syn_local_neigh_mac_info_to_peer(struct LocalInterface *local_if, int sync_add,
int is_v4, int is_v6, int sync_mac, int ack, int is_ipv6_ll, int dir);
int syn_local_mac_info_to_peer(struct CSM* csm, struct LocalInterface *local_if, int sync_add, int is_sag);
int syn_local_arp_info_to_peer(struct CSM* csm, struct LocalInterface *local_if, int sync_add, int ack);
int syn_local_nd_info_to_peer(struct CSM* csm, struct LocalInterface *local_if, int sync_add, int ack, int is_ipv6_ll, int dir);
int syn_ack_local_neigh_mac_info_to_peer(char *ifname, int is_ipv6_ll);
int is_unique_ip_configured(char *ifname);
void set_peerlink_learn_kernel(struct CSM* csm, int enable, int dir);
void set_peer_mac_in_kernel(char *mac, int vlan, int add);
void mlacp_fix_bridge_mac(struct CSM* csm);
void update_orphan_port_mac(struct CSM *csm, struct LocalInterface *lif, int state);
void mlacp_convert_remote_mac_to_local(struct CSM *csm, char *po_name);
int sync_unique_ip();
#endif

View File

@ -45,12 +45,19 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu
int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end);
int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size);
int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg, int count);
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count);
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count);
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count, int dir);
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count, int dir);
int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size);
int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if);
int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag);
int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* port_channel);
int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* peerlink_port);
int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int addr_len);
int mlacp_prepare_for_if_up_ack(
struct CSM *csm,
char *buf,
size_t max_buf_size,
uint8_t if_type,
uint16_t if_id,
uint8_t port_isolation_enable);
#endif

View File

@ -41,6 +41,7 @@ int mlacp_fsm_update_ndisc_info(struct CSM *csm, struct mLACPNDISCInfoTLV* tlv);
int mlacp_fsm_update_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv);
int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv);
void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg);
void mlacp_enqueue_ndisc(struct CSM *csm, struct Msg *msg);
int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf);

View File

@ -28,6 +28,9 @@
#include "../include/msg_format.h"
#include "../include/port.h"
#include "../include/openbsd_tree.h"
#include "../include/mlacp_tlv.h"
#define MLACP_SYSCONF_NODEID_MSB_MASK 0x80
#define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70
@ -350,7 +353,8 @@ struct mLACPVLANInfoTLV
struct mLACPMACData
{
uint8_t type;/*add or del*/
char mac_str[ETHER_ADDR_STR_LEN];
uint8_t mac_type;
uint8_t mac_addr[ETHER_ADDR_LEN];
uint16_t vid;
/*Current if name that set in chip*/
char ifname[MAX_L_PORT_NAME];
@ -366,17 +370,24 @@ struct mLACPMACInfoTLV
struct mLACPMACData MacEntry[0];
} __attribute__ ((packed));
#define NEIGH_LOCAL 1
#define NEIGH_REMOTE 2
struct ARPMsg
{
uint8_t op_type;
uint8_t flag;
uint8_t learn_flag; /*Loacl or Remote*/
char ifname[MAX_L_PORT_NAME];
uint32_t ipv4_addr;
uint32_t ipv4_addr; // net order
uint8_t mac_addr[ETHER_ADDR_LEN];
};
struct NDISCMsg
{
uint8_t op_type;
uint8_t flag;
uint8_t learn_flag; /*Loacl or Remote*/
char ifname[MAX_L_PORT_NAME];
uint32_t ipv6_addr[4];
uint8_t mac_addr[ETHER_ADDR_LEN];
@ -432,11 +443,50 @@ struct mLACPWarmbootTLV
uint8_t warmboot;
} __attribute__ ((packed));
/*
* NOS: interface up ack message
* ACK is sent by MLAG peer after processing MLAG interface up notification.
* The ack indicates that port-isolation is applied on the MLAG peer node
*/
typedef uint8_t PORT_ISOLATION_STATE_e;
enum PORT_ISOLATION_STATE_e
{
PORT_ISOLATION_STATE_DISABLE = 0,
PORT_ISOLATION_STATE_ENABLE = 1
};
typedef uint8_t IF_UP_ACK_TYPE_e;
enum IF_UP_ACK_TYPE_e
{
IF_UP_ACK_TYPE_PHY_PORT = 0,
IF_UP_ACK_TYPE_PORT_CHANNEL = 1
};
struct mLACPIfUpAckTLV {
ICCParameter icc_parameter;
uint8_t if_type;
uint8_t port_isolation_state;
uint16_t if_id; /* LAG: agg_id */
}__attribute__ ((packed));
enum NEIGH_OP_TYPE
{
NEIGH_SYNC_LIF,
NEIGH_SYNC_ADD,
NEIGH_SYNC_DEL,
NEIGH_SYNC_LIF = 0,
NEIGH_SYNC_ADD = 1,
NEIGH_SYNC_DEL = 2,
};
enum NEIGH_FLAG
{
NEIGH_SYNC_FLAG_ACK = 1,
NEIGH_SYNC_FLAG_SELF_LL = 2,
NEIGH_SYNC_FLAG_SELF_IP = 4,
};
enum NEIGH_SYNC_DIR
{
NEIGH_SYNC_CLIENT_IP = 1,
NEIGH_SYNC_SELF_IP = 2,
};
enum MAC_AGE_TYPE
@ -456,20 +506,30 @@ enum MAC_TYPE
{
MAC_TYPE_STATIC = 1,
MAC_TYPE_DYNAMIC = 2,
MAC_TYPE_DYNAMIC_LOCAL = 3, /* Used while sending MAC to Syncd to program with aging enabled. */
};
struct MACMsg
{
RB_ENTRY(MACMsg) mac_entry_rb;
uint16_t vid;
uint8_t mac_addr[ETHER_ADDR_LEN];
uint8_t op_type; /*add or del*/
uint8_t fdb_type; /*static or dynamic*/
char mac_str[ETHER_ADDR_STR_LEN];
uint16_t vid;
/*Current if name that set in chip*/
char ifname[MAX_L_PORT_NAME];
/*if we set the mac to peer-link, origin_ifname store the
original if name that learned from chip*/
char origin_ifname[MAX_L_PORT_NAME];
uint8_t age_flag;/*local or peer is age?*/
uint8_t pending_local_del;
uint8_t add_to_syncd;
TAILQ_ENTRY(MACMsg) tail; // entry into mac_msg_list
};
RB_HEAD(mac_rb_tree, MACMsg);
RB_PROTOTYPE(mac_rb_tree, MACMsg, mac_entry_rb, MACMsg_compare);
#endif /* MLACP_TLV_H_ */

View File

@ -29,6 +29,11 @@
#define MAX_MSG_LOG_SIZE 128
#define ETHER_ADDR_LEN 6
/* Header version for message sent from ICCPd to Mclagsyncd */
#define ICCPD_TO_MCLAGSYNCD_HDR_VERSION 1
/*
* RFC 5561
* 4. Capability Message
@ -99,6 +104,7 @@
#define TLV_T_MLACP_MAC_INFO 0x1038
#define TLV_T_MLACP_WARMBOOT_FLAG 0x1039
#define TLV_T_MLACP_NDISC_INFO 0x103A
#define TLV_T_MLACP_IF_UP_ACK 0x103B
#define TLV_T_MLACP_LIST_END 0x104a //list end
/* Debug */
@ -178,6 +184,9 @@ static char* get_tlv_type_string(int type)
case TLV_T_MLACP_STP_INFO:
return "TLV_T_MLACP_STP_INFO";
case TLV_T_MLACP_IF_UP_ACK:
return "TLV_T_MLACP_IF_UP_ACK";
}
return "UNKNOWN";
@ -427,7 +436,11 @@ struct AppDisconnectCauseTLV
typedef enum mclag_syncd_msg_type_e_
{
MCLAG_SYNCD_MSG_TYPE_NONE = 0,
MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1
MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1,
MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN = 2,
MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE = 3,
MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES = 4,
MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP = 5
}mclag_syncd_msg_type_e;
typedef enum mclag_msg_type_e_
@ -438,7 +451,16 @@ typedef enum mclag_msg_type_e_
MCLAG_MSG_TYPE_FLUSH_FDB = 3,
MCLAG_MSG_TYPE_SET_MAC = 4,
MCLAG_MSG_TYPE_SET_FDB = 5,
MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20
MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_ENABLE = 6,
MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE = 7,
MCLAG_MSG_TYPE_SET_ICCP_STATE = 8,
MCLAG_MSG_TYPE_SET_ICCP_ROLE = 9,
MCLAG_MSG_TYPE_SET_ICCP_SYSTEM_ID = 10,
MCLAG_MSG_TYPE_DEL_ICCP_INFO = 11,
MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE = 12,
MCLAG_MSG_TYPE_DEL_REMOTE_IF_INFO = 13,
MCLAG_MSG_TYPE_SET_PEER_LINK_ISOLATION = 14,
MCLAG_MSG_TYPE_SET_ICCP_PEER_SYSTEM_ID = 15
}mclag_msg_type_e;
@ -450,9 +472,33 @@ typedef enum mclag_sub_option_type_e_
MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3,
MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4,
MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5,
MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6
MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6,
MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME = 7,
MCLAG_SUB_OPTION_TYPE_MCLAG_ID = 8,
MCLAG_SUB_OPTION_TYPE_ICCP_ROLE = 9,
MCLAG_SUB_OPTION_TYPE_SYSTEM_ID = 10,
MCLAG_SUB_OPTION_TYPE_OPER_STATUS = 11,
MCLAG_SUB_OPTION_TYPE_ISOLATION_STATE = 12,
MCLAG_SUB_OPTION_TYPE_PEER_SYSTEM_ID = 13
} mclag_sub_option_type_e;
enum MCLAG_DOMAIN_CFG_OP_TYPE {
MCLAG_CFG_OPER_NONE = 0, //NOP
MCLAG_CFG_OPER_ADD = 1, //Add domain
MCLAG_CFG_OPER_DEL = 2, //Delete domain
MCLAG_CFG_OPER_UPDATE = 3, //update domain
MCLAG_CFG_OPER_ATTR_DEL = 4 //Attribute del
};
enum MCLAG_DOMAIN_CFG_ATTR_BMAP_FLAGS {
MCLAG_CFG_ATTR_NONE = 0x0,
MCLAG_CFG_ATTR_SRC_ADDR = 0x1,
MCLAG_CFG_ATTR_PEER_ADDR = 0x2,
MCLAG_CFG_ATTR_PEER_LINK = 0x4,
MCLAG_CFG_ATTR_KEEPALIVE_INTERVAL = 0x8,
MCLAG_CFG_ATTR_SESSION_TIMEOUT = 0x10
};
struct IccpSyncdHDr
{
@ -475,13 +521,39 @@ typedef struct mclag_sub_option_hdr_t_
struct mclag_fdb_info
{
char mac[ETHER_ADDR_STR_LEN];
uint8_t mac[ETHER_ADDR_LEN];
unsigned int vid;
char port_name[MAX_L_PORT_NAME];
short type; /*dynamic or static*/
short op_type; /*add or del*/
};
struct mclag_domain_cfg_info
{
int op_type;/*add/del domain; add/del mclag domain */
int domain_id;
int keepalive_time;
int session_timeout;
char local_ip[INET_ADDRSTRLEN];
char peer_ip[INET_ADDRSTRLEN];
char peer_ifname[MAX_L_PORT_NAME];
uint8_t system_mac[ETHER_ADDR_LEN];
int attr_bmap;
};
struct mclag_iface_cfg_info
{
int op_type; /*add/del mclag iface */
int domain_id;
char mclag_iface[MAX_L_PORT_NAME];
};
struct mclag_unique_ip_cfg_info
{
int op_type;/*add/del mclag unique ip iface */
char mclag_unique_ip_ifname[MAX_L_PORT_NAME];
};
/* For storing message log: For Notification TLV */
struct MsgTypeSet
{
@ -491,6 +563,13 @@ struct MsgTypeSet
};
struct mclag_vlan_mbr_info
{
int op_type;/*add/del vlan_member */
unsigned int vid;
char mclag_iface[MAX_L_PORT_NAME];
};
struct MsgLog
{
struct MsgTypeSet msg[MAX_MSG_LOG_SIZE];

View File

@ -0,0 +1,571 @@
/* $OpenBSD: tree.h,v 1.14 2015/05/25 03:07:49 deraadt Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SYS_TREE_H_
#define _SYS_TREE_H_
/*
* This file defines data structures for different types of trees:
* splay trees and red-black trees.
*
* A splay tree is a self-organizing data structure. Every operation
* on the tree causes a splay to happen. The splay moves the requested
* node to the root of the tree and partly rebalances it.
*
* This has the benefit that request locality causes faster lookups as
* the requested nodes move to the top of the tree. On the other hand,
* every lookup causes memory writes.
*
* The Balance Theorem bounds the total access time for m operations
* and n inserts on an initially empty tree as O((m + n)lg n). The
* amortized cost for a sequence of m accesses to a splay tree is O(lg n);
*
* A red-black tree is a binary search tree with the node color as an
* extra attribute. It fulfills a set of conditions:
* - every search path from the root to a leaf consists of the
* same number of black nodes,
* - each red node (except for the root) has a black parent,
* - each leaf node is black.
*
* Every operation on a red-black tree is bounded as O(lg n).
* The maximum height of a red-black tree is 2lg (n+1).
*/
#ifndef offsetof
#ifdef __compiler_offsetof
#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif
#define SPLAY_HEAD(name, type) \
struct name { \
struct type *sph_root; /* root of the tree */ \
}
#define SPLAY_INITIALIZER(root) \
{ \
NULL \
}
#define SPLAY_INIT(root) \
do { \
(root)->sph_root = NULL; \
} while (0)
#define SPLAY_ENTRY(type) \
struct { \
struct type *spe_left; /* left element */ \
struct type *spe_right; /* right element */ \
}
#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
#define SPLAY_ROOT(head) (head)->sph_root
#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
#define SPLAY_ROTATE_RIGHT(head, tmp, field) \
do { \
SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
#define SPLAY_ROTATE_LEFT(head, tmp, field) \
do { \
SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
(head)->sph_root = tmp; \
} while (0)
#define SPLAY_LINKLEFT(head, tmp, field) \
do { \
SPLAY_LEFT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
} while (0)
#define SPLAY_LINKRIGHT(head, tmp, field) \
do { \
SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
tmp = (head)->sph_root; \
(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
} while (0)
#define SPLAY_ASSEMBLE(head, node, left, right, field) \
do { \
SPLAY_RIGHT(left, field) = \
SPLAY_LEFT((head)->sph_root, field); \
SPLAY_LEFT(right, field) = \
SPLAY_RIGHT((head)->sph_root, field); \
SPLAY_LEFT((head)->sph_root, field) = \
SPLAY_RIGHT(node, field); \
SPLAY_RIGHT((head)->sph_root, field) = \
SPLAY_LEFT(node, field); \
} while (0)
/* Generates prototypes and inline functions */
#define SPLAY_PROTOTYPE(name, type, field, cmp) \
void name##_SPLAY(struct name *, struct type *); \
void name##_SPLAY_MINMAX(struct name *, int); \
struct type *name##_SPLAY_INSERT(struct name *, struct type *); \
struct type *name##_SPLAY_REMOVE(struct name *, struct type *); \
\
/* Finds the node with the same key as elm */ \
static __inline struct type *name##_SPLAY_FIND(struct name *head, \
struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) \
return (head->sph_root); \
return (NULL); \
} \
\
static __inline struct type *name##_SPLAY_NEXT(struct name *head, \
struct type *elm) \
{ \
name##_SPLAY(head, elm); \
if (SPLAY_RIGHT(elm, field) != NULL) { \
elm = SPLAY_RIGHT(elm, field); \
while (SPLAY_LEFT(elm, field) != NULL) { \
elm = SPLAY_LEFT(elm, field); \
} \
} else \
elm = NULL; \
return (elm); \
} \
\
static __inline struct type *name##_SPLAY_MIN_MAX(struct name *head, \
int val) \
{ \
name##_SPLAY_MINMAX(head, val); \
return (SPLAY_ROOT(head)); \
}
/* Main splay operation.
* Moves node close to the key of elm to top
*/
#define SPLAY_GENERATE(name, type, field, cmp) \
struct type *name##_SPLAY_INSERT(struct name *head, struct type *elm) \
{ \
if (SPLAY_EMPTY(head)) { \
SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = \
NULL; \
} else { \
int __comp; \
name##_SPLAY(head, elm); \
__comp = (cmp)(elm, (head)->sph_root); \
if (__comp < 0) { \
SPLAY_LEFT(elm, field) = \
SPLAY_LEFT((head)->sph_root, field); \
SPLAY_RIGHT(elm, field) = (head)->sph_root; \
SPLAY_LEFT((head)->sph_root, field) = NULL; \
} else if (__comp > 0) { \
SPLAY_RIGHT(elm, field) = \
SPLAY_RIGHT((head)->sph_root, field); \
SPLAY_LEFT(elm, field) = (head)->sph_root; \
SPLAY_RIGHT((head)->sph_root, field) = NULL; \
} else \
return ((head)->sph_root); \
} \
(head)->sph_root = (elm); \
return (NULL); \
} \
\
struct type *name##_SPLAY_REMOVE(struct name *head, struct type *elm) \
{ \
struct type *__tmp; \
if (SPLAY_EMPTY(head)) \
return (NULL); \
name##_SPLAY(head, elm); \
if ((cmp)(elm, (head)->sph_root) == 0) { \
if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
(head)->sph_root = \
SPLAY_RIGHT((head)->sph_root, field); \
} else { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
(head)->sph_root = \
SPLAY_LEFT((head)->sph_root, field); \
name##_SPLAY(head, elm); \
SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
} \
return (elm); \
} \
return (NULL); \
} \
\
void name##_SPLAY(struct name *head, struct type *elm) \
{ \
struct type __node, *__left, *__right, *__tmp; \
int __comp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \
NULL; \
__left = __right = &__node; \
\
while ((__comp = (cmp)(elm, (head)->sph_root))) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) < 0) { \
SPLAY_ROTATE_RIGHT(head, __tmp, \
field); \
if (SPLAY_LEFT((head)->sph_root, \
field) \
== NULL) \
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if ((cmp)(elm, __tmp) > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, \
field) \
== NULL) \
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
} \
\
/* Splay with either the minimum or the maximum element \
* Used to find minimum or maximum element in tree. \
*/ \
void name##_SPLAY_MINMAX(struct name *head, int __comp) \
{ \
struct type __node, *__left, *__right, *__tmp; \
\
SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = \
NULL; \
__left = __right = &__node; \
\
while (1) { \
if (__comp < 0) { \
__tmp = SPLAY_LEFT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp < 0) { \
SPLAY_ROTATE_RIGHT(head, __tmp, \
field); \
if (SPLAY_LEFT((head)->sph_root, \
field) \
== NULL) \
break; \
} \
SPLAY_LINKLEFT(head, __right, field); \
} else if (__comp > 0) { \
__tmp = SPLAY_RIGHT((head)->sph_root, field); \
if (__tmp == NULL) \
break; \
if (__comp > 0) { \
SPLAY_ROTATE_LEFT(head, __tmp, field); \
if (SPLAY_RIGHT((head)->sph_root, \
field) \
== NULL) \
break; \
} \
SPLAY_LINKRIGHT(head, __left, field); \
} \
} \
SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
}
#define SPLAY_NEGINF -1
#define SPLAY_INF 1
#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
#define SPLAY_MIN(name, x) \
(SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
#define SPLAY_MAX(name, x) \
(SPLAY_EMPTY(x) ? NULL : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
#define SPLAY_FOREACH(x, name, head) \
for ((x) = SPLAY_MIN(name, head); (x) != NULL; \
(x) = SPLAY_NEXT(name, head, x))
/*
* Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#define RB_BLACK 0
#define RB_RED 1
struct rb_type {
int (*t_compare)(const void *, const void *);
void (*t_augment)(void *);
unsigned int t_offset; /* offset of rb_entry in type */
};
struct rbt_tree {
struct rb_entry *rbt_root;
};
struct rb_entry {
struct rb_entry *rbt_parent;
struct rb_entry *rbt_left;
struct rb_entry *rbt_right;
unsigned int rbt_color;
};
#define RB_HEAD(_name, _type) \
struct _name { \
struct rbt_tree rbh_root; \
}
#define RB_ENTRY(_type) struct rb_entry
static inline void _rb_init(struct rbt_tree *rbt)
{
rbt->rbt_root = NULL;
}
static inline int _rb_empty(struct rbt_tree *rbt)
{
return (rbt->rbt_root == NULL);
}
void *_rb_insert(const struct rb_type *, struct rbt_tree *, void *);
void *_rb_remove(const struct rb_type *, struct rbt_tree *, void *);
void *_rb_find(const struct rb_type *, struct rbt_tree *, const void *);
void *_rb_nfind(const struct rb_type *, struct rbt_tree *, const void *);
void *_rb_root(const struct rb_type *, struct rbt_tree *);
void *_rb_min(const struct rb_type *, struct rbt_tree *);
void *_rb_max(const struct rb_type *, struct rbt_tree *);
void *_rb_next(const struct rb_type *, void *);
void *_rb_prev(const struct rb_type *, void *);
void *_rb_left(const struct rb_type *, void *);
void *_rb_right(const struct rb_type *, void *);
void *_rb_parent(const struct rb_type *, void *);
void _rb_set_left(const struct rb_type *, void *, void *);
void _rb_set_right(const struct rb_type *, void *, void *);
void _rb_set_parent(const struct rb_type *, void *, void *);
void _rb_poison(const struct rb_type *, void *, unsigned long);
int _rb_check(const struct rb_type *, void *, unsigned long);
#define RB_INITIALIZER(_head) { { NULL } }
#define RB_PROTOTYPE(_name, _type, _field, _cmp) \
extern const struct rb_type *const _name##_RB_TYPE; \
\
__attribute__((__unused__)) static inline void _name##_RB_INIT( \
struct _name *head) \
{ \
_rb_init(&head->rbh_root); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_INSERT(struct _name *head, struct _type *elm) \
{ \
return _rb_insert(_name##_RB_TYPE, &head->rbh_root, elm); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_REMOVE(struct _name *head, struct _type *elm) \
{ \
return _rb_remove(_name##_RB_TYPE, &head->rbh_root, elm); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_FIND(struct _name *head, const struct _type *key) \
{ \
return _rb_find(_name##_RB_TYPE, &head->rbh_root, key); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_NFIND(struct _name *head, const struct _type *key) \
{ \
return _rb_nfind(_name##_RB_TYPE, &head->rbh_root, key); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_ROOT(struct _name *head) \
{ \
return _rb_root(_name##_RB_TYPE, &head->rbh_root); \
} \
\
__attribute__((__unused__)) static inline int _name##_RB_EMPTY( \
struct _name *head) \
{ \
return _rb_empty(&head->rbh_root); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_MIN(struct _name *head) \
{ \
return _rb_min(_name##_RB_TYPE, &head->rbh_root); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_MAX(struct _name *head) \
{ \
return _rb_max(_name##_RB_TYPE, &head->rbh_root); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_NEXT(struct _type *elm) \
{ \
return _rb_next(_name##_RB_TYPE, elm); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_PREV(struct _type *elm) \
{ \
return _rb_prev(_name##_RB_TYPE, elm); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_LEFT(struct _type *elm) \
{ \
return _rb_left(_name##_RB_TYPE, elm); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_RIGHT(struct _type *elm) \
{ \
return _rb_right(_name##_RB_TYPE, elm); \
} \
\
__attribute__((__unused__)) static inline struct _type \
*_name##_RB_PARENT(struct _type *elm) \
{ \
return _rb_parent(_name##_RB_TYPE, elm); \
} \
\
__attribute__((__unused__)) static inline void _name##_RB_SET_LEFT( \
struct _type *elm, struct _type *left) \
{ \
_rb_set_left(_name##_RB_TYPE, elm, left); \
} \
\
__attribute__((__unused__)) static inline void _name##_RB_SET_RIGHT( \
struct _type *elm, struct _type *right) \
{ \
_rb_set_right(_name##_RB_TYPE, elm, right); \
} \
\
__attribute__((__unused__)) static inline void _name##_RB_SET_PARENT( \
struct _type *elm, struct _type *parent) \
{ \
_rb_set_parent(_name##_RB_TYPE, elm, parent); \
} \
\
__attribute__((__unused__)) static inline void _name##_RB_POISON( \
struct _type *elm, unsigned long poison) \
{ \
_rb_poison(_name##_RB_TYPE, elm, poison); \
} \
\
__attribute__((__unused__)) static inline int _name##_RB_CHECK( \
struct _type *elm, unsigned long poison) \
{ \
return _rb_check(_name##_RB_TYPE, elm, poison); \
}
#define RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _aug) \
static int _name##_RB_COMPARE(const void *lptr, const void *rptr) \
{ \
const struct _type *l = lptr, *r = rptr; \
return _cmp(l, r); \
} \
static const struct rb_type _name##_RB_INFO = { \
_name##_RB_COMPARE, _aug, offsetof(struct _type, _field), \
}; \
const struct rb_type *const _name##_RB_TYPE = &_name##_RB_INFO;
#define RB_GENERATE_AUGMENT(_name, _type, _field, _cmp, _aug) \
static void _name##_RB_AUGMENT(void *ptr) \
{ \
struct _type *p = ptr; \
return _aug(p); \
} \
RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, _name##_RB_AUGMENT)
#define RB_GENERATE(_name, _type, _field, _cmp) \
RB_GENERATE_INTERNAL(_name, _type, _field, _cmp, NULL)
#define RB_INIT(_name, _head) _name##_RB_INIT(_head)
#define RB_INSERT(_name, _head, _elm) _name##_RB_INSERT(_head, _elm)
#define RB_REMOVE(_name, _head, _elm) _name##_RB_REMOVE(_head, _elm)
#define RB_FIND(_name, _head, _key) _name##_RB_FIND(_head, _key)
#define RB_NFIND(_name, _head, _key) _name##_RB_NFIND(_head, _key)
#define RB_ROOT(_name, _head) _name##_RB_ROOT(_head)
#define RB_EMPTY(_name, _head) _name##_RB_EMPTY(_head)
#define RB_MIN(_name, _head) _name##_RB_MIN(_head)
#define RB_MAX(_name, _head) _name##_RB_MAX(_head)
#define RB_NEXT(_name, _elm) _name##_RB_NEXT(_elm)
#define RB_PREV(_name, _elm) _name##_RB_PREV(_elm)
#define RB_LEFT(_name, _elm) _name##_RB_LEFT(_elm)
#define RB_RIGHT(_name, _elm) _name##_RB_RIGHT(_elm)
#define RB_PARENT(_name, _elm) _name##_RB_PARENT(_elm)
#define RB_SET_LEFT(_name, _elm, _l) _name##_RB_SET_LEFT(_elm, _l)
#define RB_SET_RIGHT(_name, _elm, _r) _name##_RB_SET_RIGHT(_elm, _r)
#define RB_SET_PARENT(_name, _elm, _p) _name##_RB_SET_PARENT(_elm, _p)
#define RB_POISON(_name, _elm, _p) _name##_RB_POISON(_elm, _p)
#define RB_CHECK(_name, _elm, _p) _name##_RB_CHECK(_elm, _p)
#define RB_FOREACH(_e, _name, _head) \
for ((_e) = RB_MIN(_name, (_head)); (_e) != NULL; \
(_e) = RB_NEXT(_name, (_e)))
#define RB_FOREACH_SAFE(_e, _name, _head, _n) \
for ((_e) = RB_MIN(_name, (_head)); \
(_e) != NULL && ((_n) = RB_NEXT(_name, (_e)), 1); (_e) = (_n))
#define RB_FOREACH_REVERSE(_e, _name, _head) \
for ((_e) = RB_MAX(_name, (_head)); (_e) != NULL; \
(_e) = RB_PREV(_name, (_e)))
#define RB_FOREACH_REVERSE_SAFE(_e, _name, _head, _n) \
for ((_e) = RB_MAX(_name, (_head)); \
(_e) != NULL && ((_n) = RB_PREV(_name, (_e)), 1); (_e) = (_n))
#endif /* _SYS_TREE_H_ */

View File

@ -25,9 +25,17 @@
#define PORT_H_
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <sys/queue.h>
#include "../include/openbsd_tree.h"
#ifndef INET_ADDRSTRLEN
#define INET_ADDRSTRLEN 16
#endif /* INET_ADDRSTRLEN */
#define ETHER_ADDR_LEN 6
#define ETHER_ADDR_STR_LEN 18
/*
@ -50,6 +58,7 @@
#define IF_T_VLAN 2
#define IF_T_VXLAN 3
#define IF_T_BRIDGE 4
typedef struct
{
char *ifname;
@ -62,14 +71,38 @@ struct If_info
LIST_ENTRY(If_info) csm_next;
};
struct Unq_ip_If_info
{
char name[MAX_L_PORT_NAME];
LIST_ENTRY(Unq_ip_If_info) if_next;
};
struct VLAN_ID
{
uint16_t vid;
uint16_t vlan_removed;
struct LocalInterface* vlan_itf; /* loacl vlan interface */
LIST_ENTRY(VLAN_ID) port_next;
RB_ENTRY(VLAN_ID) vlan_entry;
};
RB_HEAD(vlan_rb_tree, VLAN_ID);
RB_PROTOTYPE(vlan_rb_tree, VLAN_ID, vlan_rb_tree, vlan_node_compare);
struct PendingVlanMbrIf
{
char name[MAX_L_PORT_NAME];
struct vlan_rb_tree vlan_tree;
LIST_ENTRY(PendingVlanMbrIf) if_next;
};
#define VLAN_RB_REMOVE(name, head, elm) do { \
RB_REMOVE(name, head, elm); \
(elm)->vlan_entry.rbt_parent = NULL; \
(elm)->vlan_entry.rbt_left = NULL; \
(elm)->vlan_entry.rbt_right = NULL; \
} while (0)
struct PeerInterface
{
int ifindex;
@ -88,7 +121,7 @@ struct PeerInterface
struct CSM* csm;
LIST_ENTRY(PeerInterface) mlacp_next;
LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list;
struct vlan_rb_tree vlan_tree;
};
struct LocalInterface
@ -104,6 +137,8 @@ struct LocalInterface
uint8_t prefixlen;
uint32_t ipv6_addr[4];
uint8_t prefixlen_v6;
uint32_t ipv6_ll_addr[4];
uint8_t ll_prefixlen_v6;
uint8_t l3_mode;
uint8_t l3_mac_addr[ETHER_ADDR_LEN];
@ -115,12 +150,18 @@ struct LocalInterface
int mlacp_state; /* Record mlacp state */
uint8_t isolate_to_peer_link;
time_t po_down_time;
struct CSM* csm;
uint8_t changed;
uint8_t port_config_sync;
bool is_traffic_disable; /* Disable traffic tx/rx */
bool is_l3_proto_enabled; /* Enable L3 Protocol support */
uint32_t vlan_count;
uint32_t master_ifindex; /* VRF ifindex*/
LIST_HEAD(local_vlan_list, VLAN_ID) vlan_list;
struct vlan_rb_tree vlan_tree;
LIST_ENTRY(LocalInterface) system_next;
LIST_ENTRY(LocalInterface) system_purge_next;
@ -128,7 +169,7 @@ struct LocalInterface
LIST_ENTRY(LocalInterface) mlacp_purge_next;
};
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type);
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type, uint8_t state);
struct LocalInterface* local_if_find_by_name(const char* ifname);
struct LocalInterface* local_if_find_by_ifindex(int ifindex);
struct LocalInterface* local_if_find_by_po_id(int po_id);
@ -141,7 +182,6 @@ int local_if_is_l3_mode(struct LocalInterface* local_if);
void local_if_init(struct LocalInterface*);
void local_if_finalize(struct LocalInterface*);
void ether_mac_set_addr_with_if_name(char *name, uint8_t* mac);
struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type);
struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name);

View File

@ -56,5 +56,6 @@ int scheduler_csm_read_callback(struct CSM* csm);
int iccp_get_server_sock_fd();
int scheduler_server_accept();
int iccp_receive_signal_handler(struct System* sys);
void scheduler_csm_socket_cleanup(struct CSM* csm, int location);
#endif /* SCHEDULER_H_ */

View File

@ -34,6 +34,7 @@
#include <unistd.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include "../include/port.h"
@ -52,6 +53,245 @@ struct CSM;
#define MAX_BUFSIZE 4096
#endif
extern char mac_print_str[ETHER_ADDR_STR_LEN];
#define MAC_IN_MSG_LIST(head, elm, field) \
(((elm)->field.tqe_next != NULL) || \
((elm)->field.tqe_prev != NULL))
#define CLEAR_MAC_IN_MSG_LIST(head, elm, field) \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = NULL;
#define MAC_TAILQ_REMOVE(head, elm, field) do { \
TAILQ_REMOVE(head, elm, field); \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = NULL; \
} while (/*CONSTCOND*/0)
#define MAC_RB_REMOVE(name, head, elm) do { \
RB_REMOVE(name, head, elm); \
(elm)->mac_entry_rb.rbt_parent = NULL; \
(elm)->mac_entry_rb.rbt_left = NULL; \
(elm)->mac_entry_rb.rbt_right = NULL; \
} while (/*CONSTCOND*/0)
/* Debug counters */
/* Debug counters to track messages ICCPd sent to MclagSyncd */
typedef uint8_t SYNCD_DBG_CNTR_STS_e;
enum SYNCD_DBG_CNTR_STS_e
{
SYNCD_DBG_CNTR_STS_OK = 0,
SYNCD_DBG_CNTR_STS_ERR = 1, /* Send error or receive processing error*/
SYNCD_DBG_CNTR_STS_MAX
};
typedef uint8_t SYNCD_TX_DBG_CNTR_MSG_e;
enum SYNCD_TX_DBG_CNTR_MSG_e
{
SYNCD_TX_DBG_CNTR_MSG_PORT_ISOLATE = 0,
SYNCD_TX_DBG_CNTR_MSG_PORT_MAC_LEARN_MODE = 1,
SYNCD_TX_DBG_CNTR_MSG_FLUSH_FDB = 2,
SYNCD_TX_DBG_CNTR_MSG_SET_IF_MAC = 3,
SYNCD_TX_DBG_CNTR_MSG_SET_FDB = 4,
SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_ENABLE = 5,
SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_DISABLE = 6,
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_STATE = 7,
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_ROLE = 8,
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_SYSTEM_ID = 9,
SYNCD_TX_DBG_CNTR_MSG_DEL_ICCP_INFO = 10,
SYNCD_TX_DBG_CNTR_MSG_SET_REMOTE_IF_STATE = 11,
SYNCD_TX_DBG_CNTR_MSG_DEL_REMOTE_IF_INFO = 12,
SYNCD_TX_DBG_CNTR_MSG_PEER_LINK_ISOLATION = 13,
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_PEER_SYSTEM_ID = 14,
SYNCD_TX_DBG_CNTR_MSG_MAX
};
typedef uint8_t SYNCD_RX_DBG_CNTR_MSG_e;
enum SYNCD_RX_DBG_CNTR_MSG_e
{
SYNCD_RX_DBG_CNTR_MSG_MAC = 0,
SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_DOMAIN = 1,
SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_IFACE = 2,
SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_UNIQUE_IP = 3,
SYNCD_RX_DBG_CNTR_MSG_VLAN_MBR_UPDATES = 4,
SYNCD_RX_DBG_CNTR_MSG_MAX
};
/* Count messages ICCP daemon sent to MclagSyncd */
#define SYSTEM_SET_SYNCD_TX_DBG_COUNTER(sys, syncd_msg_type, status)\
do{\
SYNCD_TX_DBG_CNTR_MSG_e dbg_type;\
dbg_type = system_syncdtx_to_dbg_msg_type(syncd_msg_type);\
if (sys && ((dbg_type) < SYNCD_TX_DBG_CNTR_MSG_MAX) && ((status) < SYNCD_DBG_CNTR_STS_MAX))\
{\
++sys->dbg_counters.syncd_tx_counters[dbg_type][status];\
}\
}while(0);
/* Count messages ICCP daemon received from MclagSyncd */
#define SYSTEM_SET_SYNCD_RX_DBG_COUNTER(sys, syncd_msg_type, status)\
do{\
SYNCD_RX_DBG_CNTR_MSG_e dbg_type;\
dbg_type = system_syncdrx_to_dbg_msg_type(syncd_msg_type);\
if (sys && ((dbg_type) < SYNCD_RX_DBG_CNTR_MSG_MAX) && ((status) < SYNCD_DBG_CNTR_STS_MAX))\
{\
++sys->dbg_counters.syncd_rx_counters[dbg_type][status];\
}\
}while(0);
#define SYSTEM_INCR_SESSION_DOWN_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.session_down_counter;\
#define SYSTEM_GET_SESSION_DOWN_COUNTER(sys)\
( (sys) ? (sys)->dbg_counters.session_down_counter: 0)
#define SYSTEM_INCR_PEER_LINK_DOWN_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.peer_link_down_counter;\
#define SYSTEM_INCR_WARMBOOT_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.warmboot_counter;
#define SYSTEM_INCR_INVALID_PEER_MSG_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_peer_invalid_msg_counter;
#define SYSTEM_GET_INVALID_PEER_MSG_COUNTER(sys)\
((sys) ? ((sys)->dbg_counters.rx_peer_invalid_msg_counter) ? 0)
#define SYSTEM_INCR_RX_READ_SOCK_ZERO_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_read_sock_zero_len_counter;
#define SYSTEM_INCR_HDR_READ_SOCK_ERR_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_peer_hdr_read_sock_err_counter;
#define SYSTEM_INCR_HDR_READ_SOCK_ZERO_LEN_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_peer_hdr_read_sock_zero_len_counter;
#define SYSTEM_INCR_TLV_READ_SOCK_ERR_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_peer_tlv_read_sock_err_counter;
#define SYSTEM_INCR_TLV_READ_SOCK_ZERO_LEN_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_peer_tlv_read_sock_zero_len_counter;
#define SYSTEM_INCR_SOCKET_CLOSE_ERR_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.socket_close_err_counter;
#define SYSTEM_INCR_SOCKET_CLEANUP_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.socket_cleanup_counter;
#define SYSTEM_INCR_RX_RETRY_FAIL_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_retry_fail_counter;
#define SYSTEM_INCR_MAC_ENTRY_ALLOC_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.mac_entry_alloc_counter;
#define SYSTEM_INCR_MAC_ENTRY_FREE_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.mac_entry_free_counter;
#define SYSTEM_INCR_RX_READ_SOCK_ZERO_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_read_sock_zero_len_counter;
#define SYSTEM_INCR_RX_READ_SOCK_ERR_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_read_sock_err_counter;
#define SYSTEM_INCR_RX_READ_STP_SOCK_ZERO_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_read_stp_sock_zero_len_counter;
#define SYSTEM_INCR_RX_READ_STP_SOCK_ERR_COUNTER(sys)\
if (sys)\
++sys->dbg_counters.rx_read_stp_sock_err_counter;
#define SYSTEM_SET_RETRY_COUNTER(sys, num_retry)\
if (sys)\
{\
sys->dbg_counters.rx_retry_total_counter += num_retry;\
if (num_retry > sys->dbg_counters.rx_retry_max_counter)\
sys->dbg_counters.rx_retry_max_counter = num_retry;\
}
#define SYSTEM_INCR_NETLINK_UNKNOWN_IF_NAME(ifname)\
do {\
struct System *sys;\
sys = system_get_instance();\
if (sys)\
{\
++sys->dbg_counters.unknown_if_name_count;\
if (sys->dbg_counters.unknown_if_name_count < 10)\
{\
ICCPD_LOG_NOTICE("ICCP_FSM","NETLINK_COUNTER: Unknown if_name %s", ifname);\
}\
}\
}while(0)
#define SYSTEM_INCR_NETLINK_RX_ERROR()\
do {\
struct System *sys;\
sys = system_get_instance();\
if (sys)\
++sys->dbg_counters.rx_error_count;\
}while(0)
typedef struct system_dbg_counter_info
{
/* Netlink message counters */
uint32_t newlink_count;
uint32_t dellink_count;
uint32_t newnbr_count;
uint32_t delnbr_count;
uint32_t newaddr_count;
uint32_t deladdr_count;
uint32_t unknown_type_count;
uint32_t rx_error_count;
/* Netlink link sub-message count */
uint32_t unknown_if_name_count;
/* Netlink neighbor sub-message count */
uint32_t newmac_count;
uint32_t delmac_count;
uint32_t session_down_counter; //not counting down due to warmboot
uint32_t peer_link_down_counter;
uint32_t warmboot_counter;
uint32_t rx_peer_invalid_msg_counter; //counts partial msgs received as sending end is not sending partial msgs
uint32_t rx_peer_hdr_read_sock_err_counter; //counts socket header read errors
uint32_t rx_peer_hdr_read_sock_zero_len_counter; //counts socket header read zero length
uint32_t rx_peer_tlv_read_sock_err_counter; //counts socket data/tlv read errors
uint32_t rx_peer_tlv_read_sock_zero_len_counter; //counts socket data/tlv read zero length
uint32_t socket_close_err_counter; //socket close failure
uint32_t socket_cleanup_counter; //socket cleanup outside of session down
uint32_t rx_retry_max_counter; //max non-blocking RX retry for one message
uint32_t rx_retry_total_counter; //total number of non-blocking RX retry
uint32_t rx_retry_fail_counter; //total number of non-blocking RX retry failure
uint32_t rx_read_sock_zero_len_counter; //counts socket header read zero length from sync_fd
uint32_t rx_read_sock_err_counter; //counts socket header read zero length from sync_fd
uint32_t rx_read_stp_sock_zero_len_counter; //counts socket header read zero length from syncd
uint32_t rx_read_stp_sock_err_counter; //counts socket header read zero length from syncd
uint32_t mac_entry_alloc_counter;
uint32_t mac_entry_free_counter;
uint64_t syncd_tx_counters[SYNCD_TX_DBG_CNTR_MSG_MAX][SYNCD_DBG_CNTR_STS_MAX];
uint64_t syncd_rx_counters[SYNCD_RX_DBG_CNTR_MSG_MAX][SYNCD_DBG_CNTR_STS_MAX];
}system_dbg_counter_info_t;
struct System
{
int server_fd;/* Peer-Link Socket*/
@ -78,6 +318,8 @@ struct System
LIST_HEAD(csm_list, CSM) csm_list;
LIST_HEAD(lif_all_list, LocalInterface) lif_list;
LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_list;
LIST_HEAD(unq_ip_all_if_list, Unq_ip_If_info) unq_ip_if_list;
LIST_HEAD(pending_vlan_mbr_if_list, PendingVlanMbrIf) pending_vlan_mbr_if_list;
/* Settings */
char* log_file_path;
@ -91,13 +333,23 @@ struct System
time_t csm_trans_time;
int need_sync_team_again;
int need_sync_netlink_again;
/* ICCDd/MclagSyncd debug counters */
system_dbg_counter_info_t dbg_counters;
};
struct CSM* system_create_csm();
struct CSM* system_get_csm_by_peer_ip(const char*);
struct CSM* system_get_csm_by_peer_ifname(char *ifname);
struct CSM* system_get_csm_by_mlacp_id(int id);
struct CSM* system_get_first_csm();
struct System* system_get_instance();
void system_finalize();
void system_init(struct System*);
SYNCD_TX_DBG_CNTR_MSG_e system_syncdtx_to_dbg_msg_type(uint32_t msg_type);
SYNCD_RX_DBG_CNTR_MSG_e system_syncdrx_to_dbg_msg_type(uint32_t msg_type);
char *mac_addr_to_str(uint8_t mac_addr[ETHER_ADDR_LEN]);
void system_update_netlink_counters(uint16_t netlink_msg_type, struct nlmsghdr *nlh);
#endif /* SYSTEM_H_ */

View File

@ -17,6 +17,7 @@ iccpd_SOURCES = \
mlacp_link_handler.c \
mlacp_sync_prepare.c mlacp_sync_update.c\
mlacp_fsm.c \
iccp_netlink.c
iccp_netlink.c \
openbsd_tree.c
iccpd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
iccpd_LDADD = -lnl-genl-3 -lnl-route-3 -lnl-3 -lpthread

View File

@ -239,7 +239,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif)
if (lif_po->type == IF_T_PORT_CHANNEL && lif_po->po_id == lif->po_id)
{
/*if join a po member, may swss restart, reset portchannel ip mac to mclagsyncd*/
update_if_ipmac_on_standby(lif_po);
update_if_ipmac_on_standby(lif_po, 1);
return 0;
}
}

View File

@ -52,10 +52,8 @@ int unset_mc_lag_id( struct CSM *csm, uint16_t id)
if (!csm)
return MCLAG_ERROR;
/* Mlag-ID, RG-ID, MLACP-ID*/
csm->mlag_id = 0;
csm->iccp_info.icc_rg_id = 0;
csm->app_csm.mlacp.id = 0;
/* Remove ICCP info from STATE_DB */
mlacp_link_del_iccp_info(csm->mlag_id);
iccp_csm_finalize(csm);
@ -73,7 +71,9 @@ int set_peer_link(int mid, const char* ifname)
len = strlen(ifname);
if (strncmp(ifname, FRONT_PANEL_PORT_PREFIX, strlen(FRONT_PANEL_PORT_PREFIX)) != 0 && strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0 && strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) != 0)
if (strncmp(ifname, FRONT_PANEL_PORT_PREFIX, strlen(FRONT_PANEL_PORT_PREFIX)) != 0
&& strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0
&& strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) != 0)
{
ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel or VTTNL(Vxlan tunnel)", ifname);
return MCLAG_ERROR;
@ -83,8 +83,11 @@ int set_peer_link(int mid, const char* ifname)
if (csm == NULL)
return MCLAG_ERROR;
if (len > IFNAMSIZ)
if (len > MAX_L_PORT_NAME)
{
ICCPD_LOG_ERR(__FUNCTION__, "Peer-link %s, Strlen %d greater than MAX:%d ", ifname, len, MAX_L_PORT_NAME);
return MCLAG_ERROR;
}
if (strlen(csm->peer_itf_name) > 0)
{
@ -114,7 +117,7 @@ int set_peer_link(int mid, const char* ifname)
csm->mlag_id, ifname);
}
memset(csm->peer_itf_name, 0, IFNAMSIZ);
memset(csm->peer_itf_name, 0, MAX_L_PORT_NAME);
memcpy(csm->peer_itf_name, ifname, len);
/* update peer-link link handler*/
@ -128,6 +131,8 @@ int set_peer_link(int mid, const char* ifname)
if (lif->type == IF_T_PORT_CHANNEL)
iccp_get_port_member_list(lif);
set_peerlink_learn_kernel(csm, 0, 4);
}
/*disconnect the link for mac and arp sync up*/
@ -147,15 +152,17 @@ int unset_peer_link(int mid)
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
{
/*must be enabled mac learn*/
if (csm->peer_link_if)
if (csm->peer_link_if) {
set_peerlink_mlag_port_learn(csm->peer_link_if, 1);
set_peerlink_learn_kernel(csm, 1, 5);
}
}
/* update peer-link link handler*/
scheduler_session_disconnect_handler(csm);
/* clean peer-link*/
memset(csm->peer_itf_name, 0, IFNAMSIZ);
memset(csm->peer_itf_name, 0, MAX_L_PORT_NAME);
if (csm->peer_link_if)
{
csm->peer_link_if->is_peer_link = 0;
@ -282,6 +289,42 @@ int unset_peer_address(int mid)
return 0;
}
int set_keepalive_time(int mid, int keepalive_time)
{
struct CSM* csm = NULL;
size_t len = 0;
csm = system_get_csm_by_mlacp_id(mid);
if (csm == NULL)
return MCLAG_ERROR;
ICCPD_LOG_DEBUG(__FUNCTION__, "Set keepalive_time : %d", keepalive_time);
if (csm->keepalive_time != keepalive_time)
{
csm->keepalive_time = keepalive_time;
//reset heartbeat send time to send keepalive immediately
csm->heartbeat_send_time = 0;
}
return 0;
}
int set_session_timeout(int mid, int session_timeout_val)
{
struct CSM* csm = NULL;
size_t len = 0;
csm = system_get_csm_by_mlacp_id(mid);
if (csm == NULL)
return MCLAG_ERROR;
ICCPD_LOG_DEBUG(__FUNCTION__, "Set session timeout : %d", session_timeout_val);
csm->session_timeout = session_timeout_val;
return 0;
}
int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname)
{
struct CSM* csm = NULL;
@ -352,17 +395,30 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname)
|| lif_po->po_id <= 0
|| lif_po->csm == NULL)
{
if (lif_po)
{
ICCPD_LOG_DEBUG(__FUNCTION__, "CSM already detached for ifname = %s", lif_po->name);
}
return MCLAG_ERROR;
}
/* find csm*/
csm = lif_po->csm;
if(!csm)
{
ICCPD_LOG_WARN(__FUNCTION__, "unexpected condition!!!; lif->csm not found!; Detach mclag from ifname = %s", lif_po->name);
return 0;
}
ICCPD_LOG_DEBUG(__FUNCTION__, "Detach mclag id = %d from ifname = %s",
csm->mlag_id, lif_po->name);
//if it is standby node change back the mac to its original system mac
recover_if_ipmac_on_standby(lif_po, 1);
/* process link state handler before detaching it.*/
mlacp_mlag_link_del_handler(csm, lif_po);
mlacp_mlag_intf_detach_handler(csm, lif_po);
unbind_poid = lif_po->po_id;
mlacp_unbind_local_if(lif_po);
@ -377,6 +433,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname)
if (strcmp(ifname, cif->name) == 0)
LIST_REMOVE(cif, csm_next);
}
return 0;
}

View File

@ -55,6 +55,21 @@ int set_mc_lag_by_id(uint16_t mid)
return ret;
}
int unset_mc_lag_by_id(uint16_t mid)
{
int ret = 0;
struct CSM* csm = NULL;
csm = system_get_csm_by_mlacp_id(mid);
if (csm)
{
ret = unset_mc_lag_id(csm, mid);
return ret;
}
return MCLAG_ERROR;
}
#define CONFIG_LINE_LEN 512
int iccp_config_from_command(char * line)

View File

@ -20,6 +20,7 @@
*
* Maintainer: jianjun, grace Li from nephos
*/
#include <stdbool.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <net/if.h>
@ -33,6 +34,8 @@
#include "../include/iccp_cmd_show.h"
#include "../include/mlacp_link_handler.h"
extern int local_if_l3_proto_enabled(const char* ifname);
int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
{
struct mclagd_state state_info;
@ -67,6 +70,11 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
else
state_info.keepalive = 0;
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
state_info.info_sync_done = 1;
else
state_info.info_sync_done = 0;
if (mclag_id > 0)
{
if (csm->mlag_id == mclag_id)
@ -93,13 +101,15 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
if (peer_link_if)
memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6);
state_info.keepalive_time = csm->keepalive_time;
state_info.session_timeout = csm->session_timeout;
logconfig = logger_get_configuration();
memcpy(state_info.loglevel, log_level_to_string(logconfig->log_level), strlen( log_level_to_string(logconfig->log_level)));
state_info.role = csm->role_type;
str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN;
len = 0;
LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next)
{
@ -177,6 +187,7 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id)
iccpd_arp = (struct ARPMsg*)msg->buf;
mclagd_arp.op_type = iccpd_arp->op_type;
mclagd_arp.learn_flag = iccpd_arp->learn_flag;
memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname));
memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16);
memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6);
@ -219,7 +230,6 @@ int iccp_ndisc_dump(char * *buf, int *num, int mclag_id)
if (!(sys = system_get_instance()))
{
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
return EXEC_TYPE_NO_EXIST_SYS;
}
@ -243,12 +253,12 @@ int iccp_ndisc_dump(char * *buf, int *num, int mclag_id)
iccpd_ndisc = (struct NDISCMsg *)msg->buf;
mclagd_ndisc.op_type = iccpd_ndisc->op_type;
mclagd_ndisc.learn_flag = iccpd_ndisc->learn_flag;
memcpy(mclagd_ndisc.ifname, iccpd_ndisc->ifname, strlen(iccpd_ndisc->ifname));
memcpy(mclagd_ndisc.ipv6_addr, show_ipv6_str((char *)iccpd_ndisc->ipv6_addr), 46);
memcpy(mclagd_ndisc.mac_addr, iccpd_ndisc->mac_addr, 6);
memcpy(ndisc_buf + MCLAGD_REPLY_INFO_HDR + ndisc_num * sizeof(struct mclagd_ndisc_msg),
&mclagd_ndisc, sizeof(struct mclagd_ndisc_msg));
memcpy(ndisc_buf + MCLAGD_REPLY_INFO_HDR + ndisc_num * sizeof(struct mclagd_ndisc_msg), &mclagd_ndisc, sizeof(struct mclagd_ndisc_msg));
ndisc_num++;
@ -302,14 +312,13 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id)
continue;
}
TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail)
RB_FOREACH (iccpd_mac, mac_rb_tree, &MLACP(csm).mac_rb)
{
memset(&mclagd_mac, 0, sizeof(struct mclagd_mac_msg));
iccpd_mac = (struct MACMsg*)msg->buf;
mclagd_mac.op_type = iccpd_mac->op_type;
mclagd_mac.fdb_type = iccpd_mac->fdb_type;
memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, ETHER_ADDR_STR_LEN);
memcpy(mclagd_mac.mac_addr, iccpd_mac->mac_addr, ETHER_ADDR_LEN);
mclagd_mac.vid = iccpd_mac->vid;
memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname));
memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname));
@ -344,6 +353,7 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
struct System *sys = NULL;
struct CSM *csm = NULL;
struct LocalInterface *lif_po = NULL;
struct LocalInterface *lif_peer = NULL;
struct mclagd_local_if mclagd_lif;
struct VLAN_ID* vlan_id = NULL;
char * str_buf = NULL;
@ -398,7 +408,7 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
else if (lif_po->state == PORT_STATE_TEST)
memcpy(mclagd_lif.state, "Test", 4);
memcpy(mclagd_lif.ipv4_addr, show_ip_str(htonl(lif_po->ipv4_addr)), 16);
memcpy(mclagd_lif.ipv4_addr, show_ip_str(lif_po->ipv4_addr), 16);
mclagd_lif.prefixlen = lif_po->prefixlen;
mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po);
@ -422,17 +432,47 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
memcpy(mclagd_lif.mlacp_state, "ERROR", 5);
mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link;
mclagd_lif.is_traffic_disable = lif_po->is_traffic_disable;
str_buf = mclagd_lif.vlanlist;
len = 0;
LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next)
{
if (vlan_id != NULL )
int prev_vlan_id = 0;
int range = 0;
int to_be_printed = 0;
RB_FOREACH (vlan_id, vlan_rb_tree, &(lif_po->vlan_tree))
{
if (str_size - len < 4)
break;
if (!prev_vlan_id || vlan_id->vid != prev_vlan_id + 1)
{
if (range)
{
if (str_size - len < (4 + ((range)?8:0)))
{
break;
}
len += snprintf(str_buf + len, str_size - len, "- %d ", prev_vlan_id);
}
len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid);
range = 0;
to_be_printed = 0;
}
else
{
range = 1;
to_be_printed = 1;
}
prev_vlan_id = vlan_id->vid;
}
if (to_be_printed && (str_size - len > (4 + ((range)?8:0))))
{
if (prev_vlan_id)
{
len += snprintf(str_buf + len, str_size - len, "%s%d ", range?"- ":"", prev_vlan_id);
range = 0;
}
}
@ -449,6 +489,116 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
return EXEC_TYPE_FAILED;
}
}
if (csm->peer_link_if) {
lif_peer = csm->peer_link_if;
memset(&mclagd_lif, 0, sizeof(struct mclagd_local_if));
mclagd_lif.ifindex = lif_peer->ifindex;
if (lif_peer->type == IF_T_UNKNOW)
memcpy(mclagd_lif.type, "Unknown", strlen("unknown"));
else if (lif_peer->type == IF_T_PORT)
memcpy(mclagd_lif.type, "Ethernet", strlen("Ethernet"));
else if (lif_peer->type == IF_T_PORT_CHANNEL)
memcpy(mclagd_lif.type, "PortChannel", 11);
memcpy(mclagd_lif.name, lif_peer->name, MAX_L_PORT_NAME);
memcpy(mclagd_lif.mac_addr, lif_peer->mac_addr, ETHER_ADDR_LEN);
if (lif_peer->state == PORT_STATE_UP)
memcpy(mclagd_lif.state, "Up", strlen("Up"));
else if (lif_peer->state == PORT_STATE_DOWN)
memcpy(mclagd_lif.state, "Down", strlen("Down"));
else if (lif_peer->state == PORT_STATE_ADMIN_DOWN)
memcpy(mclagd_lif.state, "Admin-down", strlen("Admin-down"));
else if (lif_peer->state == PORT_STATE_TEST)
memcpy(mclagd_lif.state, "Test", strlen("Test"));
memcpy(mclagd_lif.ipv4_addr, show_ip_str(lif_peer->ipv4_addr), 16);
mclagd_lif.prefixlen = lif_peer->prefixlen;
mclagd_lif.l3_mode = local_if_is_l3_mode(lif_peer);
mclagd_lif.is_peer_link = lif_peer->is_peer_link;
memcpy(mclagd_lif.portchannel_member_buf, lif_peer->portchannel_member_buf, 512);
mclagd_lif.po_id = lif_peer->po_id;
mclagd_lif.po_active = lif_peer->po_active;
/*mlacp_state*/
if (lif_peer->mlacp_state == MLACP_STATE_INIT)
memcpy(mclagd_lif.mlacp_state, "INIT", strlen("INIT"));
else if (lif_peer->mlacp_state == MLACP_STATE_STAGE1)
memcpy(mclagd_lif.mlacp_state, "STAGE1", strlen("STAGE1"));
else if (lif_peer->mlacp_state == MLACP_STATE_STAGE2)
memcpy(mclagd_lif.mlacp_state, "STAGE2", strlen("STAGE2"));
else if (lif_peer->mlacp_state == MLACP_STATE_EXCHANGE)
memcpy(mclagd_lif.mlacp_state, "EXCHANGE", strlen("EXCHANGE"));
else if (lif_peer->mlacp_state == MLACP_STATE_ERROR)
memcpy(mclagd_lif.mlacp_state, "ERROR", strlen("ERROR"));
mclagd_lif.isolate_to_peer_link = lif_peer->isolate_to_peer_link;
mclagd_lif.is_traffic_disable = lif_peer->is_traffic_disable;
str_buf = mclagd_lif.vlanlist;
len = 0;
int prev_vlan_id = 0;
int range = 0;
int to_be_printed = 0;
RB_FOREACH (vlan_id, vlan_rb_tree, &(lif_peer->vlan_tree))
{
if (str_size - len < 4)
break;
if (!prev_vlan_id || vlan_id->vid != prev_vlan_id + 1)
{
if (range)
{
if (str_size - len < (4 + ((range)?8:0)))
{
break;
}
len += snprintf(str_buf + len, str_size - len, "- %d ", prev_vlan_id);
}
len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid);
range = 0;
to_be_printed = 0;
}
else
{
range = 1;
to_be_printed = 1;
}
prev_vlan_id = vlan_id->vid;
}
if (to_be_printed && (str_size - len > (4 + ((range)?8:0))))
{
if (prev_vlan_id)
{
len += snprintf(str_buf + len, str_size - len, "%s%d ", range?"- ":"", prev_vlan_id);
range = 0;
}
}
memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num * sizeof(struct mclagd_local_if),
&mclagd_lif, sizeof(struct mclagd_local_if));
lif_num++;
if ((lif_num + 1) * sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR))
{
lif_buf_size += MCLAGDCTL_CMD_SIZE;
lif_buf = (char*)realloc(lif_buf, lif_buf_size);
if (!lif_buf)
return EXEC_TYPE_FAILED;
}
}
}
*buf = lif_buf;
@ -473,6 +623,7 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id)
if (!(sys = system_get_instance()))
{
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
return EXEC_TYPE_NO_EXIST_SYS;
}
@ -542,3 +693,122 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id)
return EXEC_TYPE_SUCCESS;
}
/* Allocate a buffer to return the internal debug counters
* The allocated buffer should include MCLAGD_REPLY_INFO_HDR byte header
* No buffer is allocated if error is returned
*/
int iccp_cmd_dbg_counter_dump(char **buf, int *data_len, int mclag_id)
{
struct System *sys = NULL;
struct CSM *csm = NULL;
char *temp_ptr, *counter_buf = NULL;
mclagd_dbg_counter_info_t *counter_ptr;
int buf_size = 0;
int id_exist = 0;
int num_csm = 0;
bool is_first_csm;
if (!(sys = system_get_instance()))
{
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
return EXEC_TYPE_NO_EXIST_SYS;
}
if (mclag_id >0)
num_csm = 1;
else
{
LIST_FOREACH(csm, &(sys->csm_list), next)
{
++num_csm;
}
}
buf_size = MCLAGD_REPLY_INFO_HDR + sizeof(mclagd_dbg_counter_info_t) +
(sizeof(mlacp_dbg_counter_info_t) * num_csm);
counter_buf = (char*)malloc(buf_size);
if (!counter_buf)
return EXEC_TYPE_FAILED;
memset(counter_buf, 0, buf_size);
counter_ptr =
(mclagd_dbg_counter_info_t *)(counter_buf + MCLAGD_REPLY_INFO_HDR);
memcpy(&counter_ptr->system_dbg, &sys->dbg_counters, sizeof(sys->dbg_counters));
counter_ptr->num_iccp_counter_blocks = num_csm;
temp_ptr = counter_ptr->iccp_dbg_counters;
is_first_csm = true;
LIST_FOREACH(csm, &(sys->csm_list), next)
{
if (mclag_id >0)
{
if (csm->mlag_id == mclag_id)
id_exist = 1;
else
continue;
}
if (is_first_csm)
is_first_csm = false;
else
temp_ptr += sizeof(MLACP(csm).dbg_counters);
memcpy(temp_ptr, &MLACP(csm).dbg_counters,
sizeof(MLACP(csm).dbg_counters));
}
if (mclag_id >0 && !id_exist)
{
if (counter_buf)
free(counter_buf);
return EXEC_TYPE_NO_EXIST_MCLAGID;
}
*buf = counter_buf;
*data_len = buf_size - MCLAGD_REPLY_INFO_HDR;
return EXEC_TYPE_SUCCESS;
}
int iccp_unique_ip_if_dump(char **buf, int *num, int mclag_id)
{
struct System *sys = NULL;
struct mclagd_unique_ip_if mclagd_lif;
char *str_buf = NULL;
int str_size = MCLAGDCTL_PARA3_LEN - 1;
int len = 0;
int lif_num = 0;
int lif_buf_size = MCLAGDCTL_CMD_SIZE;
char *lif_buf = NULL;
struct Unq_ip_If_info* unq_ip_if = NULL;
if (!(sys = system_get_instance()))
{
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
return EXEC_TYPE_NO_EXIST_SYS;
}
lif_buf = (char*)malloc(lif_buf_size);
if (!lif_buf)
return EXEC_TYPE_FAILED;
LIST_FOREACH(unq_ip_if, &(sys->unq_ip_if_list), if_next)
{
memset(&mclagd_lif, 0, sizeof(struct mclagd_unique_ip_if));
memcpy(mclagd_lif.name, unq_ip_if->name, MAX_L_PORT_NAME);
mclagd_lif.active = local_if_l3_proto_enabled(unq_ip_if->name);
memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num * sizeof(struct mclagd_unique_ip_if),
&mclagd_lif, sizeof(struct mclagd_unique_ip_if));
lif_num++;
if ((lif_num + 1) * sizeof(struct mclagd_unique_ip_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR))
{
lif_buf_size += MCLAGDCTL_CMD_SIZE;
lif_buf = (char*)realloc(lif_buf, lif_buf_size);
if (!lif_buf)
return EXEC_TYPE_FAILED;
}
}
*buf = lif_buf;
*num = lif_num;
return EXEC_TYPE_SUCCESS;
}

View File

@ -112,13 +112,9 @@ static int iccp_check_interface_vlan(char* ifname)
if (peer_if == NULL)
return -4;
LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next)
RB_FOREACH (local_vlan, vlan_rb_tree, &(local_if->vlan_tree))
{
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next)
{
if (peer_vlan->vid == local_vlan->vid)
break;
}
peer_vlan = RB_FIND(vlan_rb_tree, &(peer_if->vlan_tree), local_vlan);
if (peer_vlan == NULL)
{
@ -126,14 +122,9 @@ static int iccp_check_interface_vlan(char* ifname)
}
}
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next)
RB_FOREACH (peer_vlan, vlan_rb_tree, &(peer_if->vlan_tree))
{
LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next)
{
if (peer_vlan->vid == local_vlan->vid)
break;
}
local_vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), peer_vlan);
if (local_vlan == NULL)
{

View File

@ -20,7 +20,7 @@
*
* Maintainer: jianjun, grace Li from nephos
*/
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@ -29,6 +29,7 @@
#include "../include/scheduler.h"
#include "../include/msg_format.h"
#include "../include/iccp_csm.h"
#include "../include/iccp_cli.h"
#include "../include/mlacp_link_handler.h"
/*****************************************
* Define
@ -121,6 +122,8 @@ void iccp_csm_init(struct CSM* csm)
memset(csm->peer_ip, 0, INET_ADDRSTRLEN);
memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME);
csm->iccp_info.icc_rg_id = 0x0;
csm->keepalive_time = CONNECT_INTERVAL_SEC;
csm->session_timeout = HEARTBEAT_TIMEOUT_SEC;
}
/* Connection State Machine instance status reset */
@ -141,6 +144,8 @@ void iccp_csm_status_reset(struct CSM* csm, int all)
csm->heartbeat_update_time = 0;
csm->peer_warm_reboot_time = 0;
csm->warm_reboot_disconn_time = 0;
csm->peer_link_learning_retry_time = 0;
csm->peer_link_learning_enable = 0;
csm->role_type = STP_ROLE_NONE;
csm->sock_read_event_ptr = NULL;
csm->peer_link_if = NULL;
@ -165,6 +170,9 @@ void iccp_csm_finalize(struct CSM* csm)
{
struct If_info * cif = NULL;
struct System* sys = NULL;
struct LocalInterface* lifp = NULL;
struct LocalInterface* local_if = NULL;
struct LocalInterface* local_if_next = NULL;
if (csm == NULL)
return;
@ -176,19 +184,38 @@ void iccp_csm_finalize(struct CSM* csm)
if (sys->warmboot_exit != WARM_REBOOT)
{
/*Enable peer link port MAC learning*/
if (csm->peer_link_if)
if (csm->peer_link_if) {
set_peerlink_mlag_port_learn(csm->peer_link_if, 1);
set_peerlink_learn_kernel(csm, 1, 1);
}
}
/* Disconnect from peer */
scheduler_session_disconnect_handler(csm);
//Delete all MCLAG interfaces
local_if = LIST_FIRST(&(MLACP(csm).lif_list));
while (local_if != NULL)
{
local_if_next = LIST_NEXT(local_if,mlacp_next);
iccp_cli_detach_mclag_domain_to_port_channel(local_if->name);
local_if = local_if_next;
}
/* Release all Connection State Machine instance */
app_csm_finalize(csm);
LIST_FOREACH(cif, &(csm->if_bind_list), csm_next)
LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next)
{
ICCPD_LOG_NOTICE(__FUNCTION__, "Resetting CSM pointer for %s", lifp->name);
lifp->csm = NULL;
}
while (!LIST_EMPTY(&(csm->if_bind_list)))
{
cif = LIST_FIRST(&(csm->if_bind_list));
LIST_REMOVE(cif,csm_next);
free(cif);
}
/* Release iccp_csm */
@ -219,6 +246,8 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
{
LDPHdr* ldp_hdr = (LDPHdr*)buf;
ICCParameter* param = NULL;
ssize_t rc;
uint16_t tlv_type;
if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0)
return MCLAG_ERROR;
@ -228,7 +257,7 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
else
param = (struct ICCParameter*)&buf[sizeof(ICCHdr)];
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(param->type), ldp_hdr->msg_type, param->type);*/
ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(ntohs(param->type)), ldp_hdr->msg_type, ntohs(param->type));
csm->msg_log.msg[csm->msg_log.end_index].msg_id = ntohl(ldp_hdr->msg_id);
csm->msg_log.msg[csm->msg_log.end_index].type = ntohs(ldp_hdr->msg_type);
csm->msg_log.msg[csm->msg_log.end_index].tlv = ntohs(param->type);
@ -236,7 +265,20 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
if (csm->msg_log.end_index >= 128)
csm->msg_log.end_index = 0;
return write(csm->sock_fd, buf, msg_len);
tlv_type = ntohs(param->type);
rc = write(csm->sock_fd, buf, msg_len);
if ((rc <= 0) || (rc != msg_len))
{
MLACP_SET_ICCP_TX_DBG_COUNTER(
csm, tlv_type, ICCP_DBG_CNTR_STS_ERR);
ICCPD_LOG_ERR("ICCP_FSM", "Failed to write msg %s/0x%x, msg_len:%d, rc %d Error:%s ", get_tlv_type_string(tlv_type), tlv_type, msg_len, rc, strerror(errno));
}
else
{
MLACP_SET_ICCP_TX_DBG_COUNTER(
csm, tlv_type, ICCP_DBG_CNTR_STS_OK);
}
return (rc);
}
/* Connection State Machine Transition */
@ -776,8 +818,34 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len)
return MCLAG_ERROR;
}
/* MAC Message initialization */
int iccp_csm_init_mac_msg(struct MACMsg **mac_msg, char* data, int len)
{
struct MACMsg* iccp_mac_msg = NULL;
if (mac_msg == NULL)
return -2;
if (data == NULL || len <= 0)
return MCLAG_ERROR;
iccp_mac_msg = (struct MACMsg*)malloc(sizeof(struct MACMsg));
if (iccp_mac_msg == NULL)
return -3;
memset(iccp_mac_msg, 0, sizeof(struct MACMsg));
memcpy(iccp_mac_msg, data, len);
*mac_msg = iccp_mac_msg;
return 0;
}
void iccp_csm_stp_role_count(struct CSM *csm)
{
struct If_info * cif = NULL;
/* decide the role, lower ip to be active & socket client*/
if (csm->role_type == STP_ROLE_NONE)
{
@ -786,12 +854,18 @@ void iccp_csm_stp_role_count(struct CSM *csm)
/* Active*/
ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]");
csm->role_type = STP_ROLE_ACTIVE;
/* Send ICCP role update and system ID */
mlacp_link_set_iccp_role(csm->mlag_id, true, MLACP(csm).system_id);
}
else
{
/* Standby*/
ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]");
csm->role_type = STP_ROLE_STANDBY;
/* Send ICCP role update */
mlacp_link_set_iccp_role(csm->mlag_id, false, NULL);
/*Set Bridge MAC to MY MAC*/
mlacp_fix_bridge_mac(csm);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -134,6 +134,7 @@ void iccpd_signal_handler(int sig)
if (err == -1 && errno == EINTR)
goto retry;
SYSTEM_INCR_WARMBOOT_COUNTER(sys);
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@ static uint32_t _iccpd_log_level_map[] =
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG,
LOG_DEBUG
};
char* log_level_to_string(int level)
@ -100,7 +100,7 @@ void log_finalize()
/*do nothing*/
}
void write_log(const int level, const char* tag, const char* format, ...)
void write_log(int level, const char* tag, const char* format, ...)
{
struct LoggerConfig* config = logger_get_configuration();
char buf[LOGBUF_SIZE];

View File

@ -29,7 +29,11 @@
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "mclagdctl.h"
#include "../../include/mlacp_fsm.h"
#include "../../include/system.h"
static int mclagdctl_sock_fd = -1;
char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock";
@ -38,11 +42,25 @@ char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock";
Already implemented command:
mclagdctl -i dump state
mclagdctl -i dump arp
mclagdctl -i dump nd
mclagdctl -i dump mac
mclagdctl -i dump unique_ip
mclagdctl -i dump portlist local
mclagdctl -i dump portlist peer
*/
#define ETHER_ADDR_LEN 6
char mac_print_str[18];
char *mac_addr_to_str(uint8_t* mac_addr)
{
memset(mac_print_str, 0, sizeof(mac_print_str));
snprintf(mac_print_str, sizeof(mac_print_str), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
return mac_print_str;
}
static struct command_type command_types[] =
{
{
@ -83,6 +101,14 @@ static struct command_type command_types[] =
.enca_msg = mclagdctl_enca_dump_mac,
.parse_msg = mclagdctl_parse_dump_mac,
},
{
.id = ID_CMDTYPE_D_A,
.parent_id = ID_CMDTYPE_D,
.info_type = INFO_TYPE_DUMP_UNIQUE_IP,
.name = "unique_ip",
.enca_msg = mclagdctl_enca_dump_unique_ip,
.parse_msg = mclagdctl_parse_dump_unique_ip,
},
{
.id = ID_CMDTYPE_D_P,
.parent_id = ID_CMDTYPE_D,
@ -104,6 +130,19 @@ static struct command_type command_types[] =
.enca_msg = mclagdctl_enca_dump_peer_portlist,
.parse_msg = mclagdctl_parse_dump_peer_portlist,
},
{
.id = ID_CMDTYPE_D_D,
.parent_id = ID_CMDTYPE_D,
.name = "debug",
},
{
.id = ID_CMDTYPE_D_D_C,
.parent_id = ID_CMDTYPE_D_D,
.info_type = INFO_TYPE_DUMP_DBG_COUNTERS,
.name = "counters",
.enca_msg = mclagdctl_enca_dump_dbg_counters,
.parse_msg = mclagdctl_parse_dump_dbg_counters,
},
{
.id = ID_CMDTYPE_C,
.name = "config",
@ -250,8 +289,18 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
{
state_info = (struct mclagd_state*)(msg + len * count);
fprintf(stdout, "%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR");
if (inet_addr(state_info->local_ip) < inet_addr(state_info->peer_ip))
{
state_info->role = 1;
}
else
{
state_info->role = 2;
}
fprintf(stdout, "%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR");
fprintf(stdout, "%s: %s\n", "MCLAG info sync is",
state_info->info_sync_done ? "completed" : "incomplete");
if (state_info->mclag_id <= 0)
fprintf(stdout, "%s: %s\n", "Domain id", "Unknown");
else
@ -260,6 +309,8 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
fprintf(stdout, "%s: %s\n", "Local Ip", state_info->local_ip);
fprintf(stdout, "%s: %s\n", "Peer Ip", state_info->peer_ip);
fprintf(stdout, "%s: %s\n", "Peer Link Interface", state_info->peer_link_if);
fprintf(stdout, "%s: %d\n", "Keepalive time", state_info->keepalive_time);
fprintf(stdout, "%s: %d\n", "sesssion Timeout ", state_info->session_timeout);
fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n",
"Peer Link Mac",
@ -267,9 +318,10 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
state_info->peer_link_mac[2], state_info->peer_link_mac[3],
state_info->peer_link_mac[4], state_info->peer_link_mac[5]);
if (state_info->role == 0)
/*if (state_info->role == 0)
fprintf(stdout, "%s: %s\n", "Role", "None");
else if (state_info->role == 1)
*/
if (state_info->role == 1)
fprintf(stdout, "%s: %s\n", "Role", "Active");
else if (state_info->role == 2)
fprintf(stdout, "%s: %s\n", "Role", "Standby");
@ -328,6 +380,7 @@ int mclagdctl_parse_dump_arp(char *msg, int data_len)
fprintf(stdout, "%-20s", "IP");
fprintf(stdout, "%-20s", "MAC");
fprintf(stdout, "%-20s", "DEV");
fprintf(stdout, "%s", "Flag");
fprintf(stdout, "\n");
len = sizeof(struct mclagd_arp_msg);
@ -344,6 +397,13 @@ int mclagdctl_parse_dump_arp(char *msg, int data_len)
arp_info->mac_addr[4], arp_info->mac_addr[5]);
fprintf(stdout, " ");
fprintf(stdout, "%-20s", arp_info->ifname);
if (arp_info->learn_flag == NEIGH_REMOTE) {
fprintf(stdout, "%s", "R");
} else if (arp_info->learn_flag == NEIGH_LOCAL) {
fprintf(stdout, "%s", "L");
} else {
fprintf(stdout, "%s", "-");
}
fprintf(stdout, "\n");
}
@ -360,6 +420,7 @@ int mclagdctl_parse_dump_ndisc(char *msg, int data_len)
fprintf(stdout, "%-52s", "IPv6");
fprintf(stdout, "%-20s", "MAC");
fprintf(stdout, "%-20s", "DEV");
fprintf(stdout, "%s", "Flag");
fprintf(stdout, "\n");
len = sizeof(struct mclagd_ndisc_msg);
@ -372,10 +433,16 @@ int mclagdctl_parse_dump_ndisc(char *msg, int data_len)
fprintf(stdout, "%-52s", ndisc_info->ipv6_addr);
fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x",
ndisc_info->mac_addr[0], ndisc_info->mac_addr[1],
ndisc_info->mac_addr[2], ndisc_info->mac_addr[3],
ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]);
ndisc_info->mac_addr[2], ndisc_info->mac_addr[3], ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]);
fprintf(stdout, " ");
fprintf(stdout, "%-20s", ndisc_info->ifname);
if (ndisc_info->learn_flag == NEIGH_REMOTE) {
fprintf(stdout, "%s", "R");
} else if (ndisc_info->learn_flag == NEIGH_LOCAL) {
fprintf(stdout, "%s", "L");
} else {
fprintf(stdout, "%s", "-");
}
fprintf(stdout, "\n");
}
@ -430,7 +497,8 @@ int mclagdctl_parse_dump_mac(char *msg, int data_len)
else
fprintf(stdout, "%-5s", "D");
fprintf(stdout, "%-20s", mac_info->mac_str);
fprintf(stdout, "%-20s", mac_addr_to_str(mac_info->mac_addr));
fprintf(stdout, "%-5d", mac_info->vid);
fprintf(stdout, "%-20s", mac_info->ifname);
fprintf(stdout, "%-20s", mac_info->origin_ifname);
@ -502,10 +570,11 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len)
fprintf(stdout, "%s: %s\n", "IsL3Interface", lif_info->l3_mode ? "Yes" : "No");
/*fprintf(stdout, "%s: %s\n", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No");*/
fprintf(stdout, "%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf);
/*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);
/*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/
fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active);
fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/
/*fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/
fprintf(stdout, "%s: %s\n", "IsIsolateWithPeerlink", lif_info->isolate_to_peer_link ? "Yes" : "No");
fprintf(stdout,"%s: %s\n" ,"IsTrafficDisable", lif_info->is_traffic_disable ? "Yes":"No");
fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist);
}
else
@ -514,6 +583,7 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len)
fprintf(stdout, "%s: %s\n", "Type", lif_info->type);
fprintf(stdout, "%s: %s\n", "PortName", lif_info->name);
fprintf(stdout, "%s: %s\n", "State", lif_info->state);
fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist);
/*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/
}
@ -584,6 +654,277 @@ int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len)
return 0;
}
int mclagdctl_enca_dump_unique_ip(char *msg, int mclag_id, int argc, char **argv)
{
struct mclagdctl_req_hdr req;
if (mclag_id <= 0)
{
fprintf(stderr, "Need to specify mclag-id through the parameter i !\n");
return MCLAG_ERROR;
}
memset(&req, 0, sizeof(struct mclagdctl_req_hdr));
req.info_type = INFO_TYPE_DUMP_UNIQUE_IP;
req.mclag_id = mclag_id;
memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr));
return 1;
}
int mclagdctl_parse_dump_unique_ip(char *msg, int data_len)
{
struct mclagd_unique_ip_if *ip_if_info = NULL;
int len = 0;
int count = 0;
int pos = 0;
for (pos = 0; pos < 60; ++pos)
fprintf(stdout, "-");
fprintf(stdout, "\n");
fprintf(stdout, "%-20s", "Ifname");
fprintf(stdout, "%-5s", "Active");
fprintf(stdout, "\n");
for (pos = 0; pos < 60; ++pos)
fprintf(stdout, "-");
fprintf(stdout, "\n");
len = sizeof(struct mclagd_unique_ip_if);
for (; data_len >= len; data_len -= len, count++)
{
ip_if_info = (struct mclagd_unique_ip_if*)(msg + len * count);
fprintf(stdout, "%-20s %-5s\n", ip_if_info->name, ip_if_info->active?"Yes":"No");
}
if (count == 0)
{
fprintf(stdout, "%s\n", "Unique IP configuration not enabled on any interface");
}
for (pos = 0; pos < 60; ++pos)
fprintf(stdout, "-");
fprintf(stdout, "\n\n");
return 0;
}
/* mclag_id parameter is optional */
int mclagdctl_enca_dump_dbg_counters(char *msg, int mclag_id, int argc, char **argv)
{
struct mclagdctl_req_hdr req;
memset(&req, 0, sizeof(struct mclagdctl_req_hdr));
req.info_type = INFO_TYPE_DUMP_DBG_COUNTERS;
req.mclag_id = mclag_id;
memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr));
return 1;
}
static char *mclagdctl_dbg_counter_iccpid2str(ICCP_DBG_CNTR_MSG_e iccp_cntr_id)
{
/* Keep the string to 15 characters.
* Update mclagdctl_parse_dump_dbg_counters if increase
*/
switch(iccp_cntr_id)
{
case ICCP_DBG_CNTR_MSG_SYS_CONFIG:
return "SysConfig";
case ICCP_DBG_CNTR_MSG_AGGR_CONFIG:
return "AggrConfig";
case ICCP_DBG_CNTR_MSG_AGGR_STATE:
return "AggrState";
case ICCP_DBG_CNTR_MSG_MAC_INFO:
return "MacInfo";
case ICCP_DBG_CNTR_MSG_ARP_INFO:
return "ArpInfo";
case ICCP_DBG_CNTR_MSG_PORTCHANNEL_INFO:
return "PoInfo";
case ICCP_DBG_CNTR_MSG_PEER_LINK_INFO:
return "PeerLinkInfo";
case ICCP_DBG_CNTR_MSG_HEART_BEAT:
return "Heartbeat";
case ICCP_DBG_CNTR_MSG_NAK:
return "Nak";
case ICCP_DBG_CNTR_MSG_SYNC_DATA:
return "SyncData";
case ICCP_DBG_CNTR_MSG_SYNC_REQ:
return "SyncReq";
case ICCP_DBG_CNTR_MSG_WARM_BOOT:
return "Warmboot";
case ICCP_DBG_CNTR_MSG_IF_UP_ACK:
return "IfUpAck";
default:
return "Unknown";
}
}
static char *mclagdctl_dbg_counter_syncdtx2str(SYNCD_TX_DBG_CNTR_MSG_e syncdtx_id)
{
/* Keep the string to 20 characters.
* Update mclagdctl_parse_dump_dbg_counters if increase
*/
switch(syncdtx_id)
{
case SYNCD_TX_DBG_CNTR_MSG_PORT_ISOLATE:
return "PortIsolation";
case SYNCD_TX_DBG_CNTR_MSG_PORT_MAC_LEARN_MODE:
return "MacLearnMode";
case SYNCD_TX_DBG_CNTR_MSG_FLUSH_FDB:
return "FlushFdb";
case SYNCD_TX_DBG_CNTR_MSG_SET_IF_MAC:
return "SetIfMac";
case SYNCD_TX_DBG_CNTR_MSG_SET_FDB:
return "SetFdb";
case SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_ENABLE:
return "TrafficDistEnable";
case SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_DISABLE:
return "TrafficDistDisable";
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_STATE:
return "SetIccpState";
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_ROLE:
return "SetIccpRole";
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_SYSTEM_ID:
return "SetSystemId";
case SYNCD_TX_DBG_CNTR_MSG_DEL_ICCP_INFO:
return "DelIccpInfo";
case SYNCD_TX_DBG_CNTR_MSG_SET_REMOTE_IF_STATE:
return "SetRemoteIntfSts";
case SYNCD_TX_DBG_CNTR_MSG_DEL_REMOTE_IF_INFO:
return "DelRemoteIntf";
case SYNCD_TX_DBG_CNTR_MSG_PEER_LINK_ISOLATION:
return "PeerLinkIsolation";
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_PEER_SYSTEM_ID:
return "SetPeerSystemId";
default:
return "Unknown";
}
}
static char *mclagdctl_dbg_counter_syncdrx2str(SYNCD_RX_DBG_CNTR_MSG_e syncdrx_id)
{
/* Keep the string to 20 characters.
* Update mclagdctl_parse_dump_dbg_counters if increase
*/
switch(syncdrx_id)
{
case SYNCD_RX_DBG_CNTR_MSG_MAC:
return "FdbChange";
case SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_DOMAIN:
return "CfgMclag";
case SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_IFACE:
return "CfgMclagIface";
case SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_UNIQUE_IP:
return "CfgMclagUniqueIp";
case SYNCD_RX_DBG_CNTR_MSG_VLAN_MBR_UPDATES:
return "vlanMbrshipChange";
default:
return "Unknown";
}
}
int mclagdctl_parse_dump_dbg_counters(char *msg, int data_len)
{
mclagd_dbg_counter_info_t *dbg_counter_p;
system_dbg_counter_info_t *sys_counter_p;
mlacp_dbg_counter_info_t *iccp_counter_p;
int i, j;
dbg_counter_p = (mclagd_dbg_counter_info_t *)msg;
sys_counter_p = (system_dbg_counter_info_t *)&dbg_counter_p->system_dbg;
/* Global counters */
fprintf(stdout, "%-20s%u\n", "ICCP session down:",
sys_counter_p->session_down_counter);
fprintf(stdout, "%-20s%u\n", "Peer link down:",
sys_counter_p->peer_link_down_counter);
fprintf(stdout, "%-20s%u\n", "Rx invalid msg:",
sys_counter_p->rx_peer_invalid_msg_counter);
fprintf(stdout, "%-20s%u\n", "Rx sock error(hdr):",
sys_counter_p->rx_peer_hdr_read_sock_err_counter);
fprintf(stdout, "%-20s%u\n", "Rx zero len(hdr):",
sys_counter_p->rx_peer_hdr_read_sock_zero_len_counter);
fprintf(stdout, "%-20s%u\n", "Rx sock error(tlv):",
sys_counter_p->rx_peer_tlv_read_sock_err_counter);
fprintf(stdout, "%-20s%u\n", "Rx zero len(tlv):",
sys_counter_p->rx_peer_tlv_read_sock_zero_len_counter);
fprintf(stdout, "%-20s%u\n", "Rx retry max:",
sys_counter_p->rx_retry_max_counter);
fprintf(stdout, "%-20s%u\n", "Rx retry total:",
sys_counter_p->rx_retry_total_counter);
fprintf(stdout, "%-20s%u\n", "Rx retry fail:",
sys_counter_p->rx_retry_fail_counter);
fprintf(stdout, "%-20s%u\n", "Socket close err:",
sys_counter_p->socket_close_err_counter);
fprintf(stdout, "%-20s%u\n", "Socket cleanup:",
sys_counter_p->socket_cleanup_counter);
fprintf(stdout, "\n");
fprintf(stdout, "%-20s%u\n\n", "Warmboot:", sys_counter_p->warmboot_counter);
/* ICCP daemon to Mclagsyncd messages */
fprintf(stdout, "%-20s%-20s%-20s\n", "ICCP to MclagSyncd", "TX_OK", "TX_ERROR");
fprintf(stdout, "%-20s%-20s%-20s\n", "------------------", "-----", "--------");
for (i = 0; i < SYNCD_TX_DBG_CNTR_MSG_MAX; ++i)
{
fprintf(stdout, "%-20s%-20lu%-20lu\n",
mclagdctl_dbg_counter_syncdtx2str(i),
sys_counter_p->syncd_tx_counters[i][0],
sys_counter_p->syncd_tx_counters[i][1]);
}
fprintf(stdout, "\n%-20s%-20s%-20s\n", "MclagSyncd to ICCP", "RX_OK", "RX_ERROR");
fprintf(stdout, "%-20s%-20s%-20s\n", "------------------", "-----", "--------");
for (i = 0; i < SYNCD_RX_DBG_CNTR_MSG_MAX; ++i)
{
fprintf(stdout, "%-20s%-20lu%-20lu\n",
mclagdctl_dbg_counter_syncdrx2str(i),
sys_counter_p->syncd_rx_counters[i][0],
sys_counter_p->syncd_rx_counters[i][1]);
}
/* Print ICCP messages exchanged between MLAG peers */
fprintf(stdout, "\n%-20s%-20s%-20s%-20s%-20s\n",
"ICCP to Peer", "TX_OK", "RX_OK", "TX_ERROR", "RX_ERROR");
fprintf(stdout, "%-20s%-20s%-20s%-20s%-20s\n",
"------------", "-----", "-----", "--------", "--------");
iccp_counter_p = (mlacp_dbg_counter_info_t *)dbg_counter_p->iccp_dbg_counters;
for (i = 0; i < dbg_counter_p->num_iccp_counter_blocks; ++i)
{
if (i > 0)
++iccp_counter_p;
for (j = 0; j < ICCP_DBG_CNTR_MSG_MAX; ++j)
{
fprintf(stdout, "%-20s%-20lu%-20lu%-20lu%-20lu\n",
mclagdctl_dbg_counter_iccpid2str(j),
iccp_counter_p->iccp_counters[j][0][0],
iccp_counter_p->iccp_counters[j][1][0],
iccp_counter_p->iccp_counters[j][0][1],
iccp_counter_p->iccp_counters[j][1][1]);
}
fprintf(stdout, "\n");
}
/* Netlink counters */
fprintf(stdout, "\nNetlink Counters\n");
fprintf(stdout, "-----------------\n");
fprintf(stdout, "Link add/del: %u/%u\n",
sys_counter_p->newlink_count, sys_counter_p->dellink_count);
fprintf(stdout, " Unknown if_name: %u\n", sys_counter_p->unknown_if_name_count);
fprintf(stdout, "Neighbor(ARP) add/del: %u/%u\n",
sys_counter_p->newnbr_count, sys_counter_p->delnbr_count);
fprintf(stdout, " MAC entry add/del: %u/%u\n",
sys_counter_p->newmac_count, sys_counter_p->delmac_count);
fprintf(stdout, "Address add/del: %u/%u\n",
sys_counter_p->newaddr_count, sys_counter_p->deladdr_count);
fprintf(stdout, "Unexpected message type: %u\n", sys_counter_p->unknown_type_count);
fprintf(stdout, "Receive error: %u\n\n", sys_counter_p->rx_error_count);
return 0;
}
int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv)
{
struct mclagdctl_req_hdr req;
@ -940,4 +1281,3 @@ int main(int argc, char **argv)
return ret;
}

View File

@ -17,7 +17,11 @@
*
* Maintainer: Jim Jiang from nephos
*/
#include <stdint.h>
#include <stdbool.h>
#include "../../include/system.h"
#define ETHER_ADDR_LEN 6
#define MCLAGDCTL_PARA1_LEN 16
#define MCLAGDCTL_PARA2_LEN 32
#define MCLAGDCTL_PARA3_LEN 64
@ -54,8 +58,11 @@ enum id_command_type
ID_CMDTYPE_D_P,
ID_CMDTYPE_D_P_L,
ID_CMDTYPE_D_P_P,
ID_CMDTYPE_D_D,
ID_CMDTYPE_D_D_C,
ID_CMDTYPE_C,
ID_CMDTYPE_C_L,
ID_CMDTYPE_C_D,
};
enum mclagdctl_notify_peer_type
@ -65,9 +72,12 @@ enum mclagdctl_notify_peer_type
INFO_TYPE_DUMP_ARP,
INFO_TYPE_DUMP_NDISC,
INFO_TYPE_DUMP_MAC,
INFO_TYPE_DUMP_UNIQUE_IP,
INFO_TYPE_DUMP_LOCAL_PORTLIST,
INFO_TYPE_DUMP_PEER_PORTLIST,
INFO_TYPE_DUMP_DBG_COUNTERS,
INFO_TYPE_CONFIG_LOGLEVEL,
INFO_TYPE_CONFIG_DOWN,
INFO_TYPE_FINISH,
};
@ -122,21 +132,28 @@ struct mclagd_state
{
int mclag_id;
int keepalive;
int info_sync_done;
char local_ip[MCLAGDCTL_INET_ADDR_LEN];
char peer_ip[MCLAGDCTL_INET_ADDR_LEN];
char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE];
unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN];
int role;
char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN];
int session_timeout;
int keepalive_time;
char loglevel[MCLAGDCTL_PARA1_LEN];
};
#define NEIGH_LOCAL 1
#define NEIGH_REMOTE 2
struct mclagd_arp_msg
{
char op_type;
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN];
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
uint8_t learn_flag;
};
struct mclagd_ndisc_msg
@ -145,13 +162,14 @@ struct mclagd_ndisc_msg
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
char ipv6_addr[MCLAGDCTL_INET6_ADDR_LEN];
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
uint8_t learn_flag;
};
struct mclagd_mac_msg
{
unsigned char op_type;/*add or del*/
unsigned char fdb_type;/*static or dynamic*/
char mac_str[ETHER_ADDR_STR_LEN];
uint8_t mac_addr[ETHER_ADDR_LEN];
unsigned short vid;
/*Current if name that set in chip*/
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
@ -178,7 +196,7 @@ struct mclagd_local_if
unsigned char po_active;
char mlacp_state[MCLAGDCTL_PARA1_LEN];
unsigned char isolate_to_peer_link;
bool is_traffic_disable;
char vlanlist[MCLAGDCTL_PARA3_LEN];
};
@ -193,6 +211,21 @@ struct mclagd_peer_if
unsigned char po_active;
};
typedef struct mclagd_dbg_counter_info
{
system_dbg_counter_info_t system_dbg;
uint8_t num_iccp_counter_blocks;
uint8_t iccp_dbg_counters[0];
/* Variable length counter buffers containing N mlacp_dbg_counter_info_t
*/
}mclagd_dbg_counter_info_t;
struct mclagd_unique_ip_if
{
int active;
char name[MCLAGDCTL_MAX_L_PORT_NANE];
};
extern int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv);
extern int mclagdctl_parse_dump_state(char *msg, int data_len);
extern int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv);
@ -208,3 +241,7 @@ extern int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len);
int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv);
int mclagdctl_parse_config_loglevel(char *msg, int data_len);
extern int mclagdctl_enca_dump_dbg_counters(char *msg, int mclag_id, int argc, char **argv);
extern int mclagdctl_parse_dump_dbg_counters(char *msg, int data_len);
extern int mclagdctl_enca_dump_unique_ip(char *msg, int mclag_id, int argc, char **argv);
extern int mclagdctl_parse_dump_unique_ip(char *msg, int data_len);

View File

@ -35,10 +35,13 @@
#include <msg_format.h>
#include <system.h>
#include <logger.h>
#include <assert.h>
#include "../include/mlacp_tlv.h"
#include "../include/mlacp_sync_prepare.h"
#include "../include/mlacp_link_handler.h"
#include "../include/mlacp_sync_update.h"
#include "../include/system.h"
#include "../include/scheduler.h"
#include <signal.h>
@ -58,6 +61,18 @@
TAILQ_INIT(&(list)); \
}
#define MLACP_MAC_MSG_QUEUE_REINIT(list) \
{ \
struct MACMsg* mac_msg = NULL; \
while (!TAILQ_EMPTY(&(list))) { \
mac_msg = TAILQ_FIRST(&(list)); \
TAILQ_REMOVE(&(list), mac_msg, tail); \
if (mac_msg->op_type == MAC_SYNC_DEL) \
free(mac_msg); \
} \
TAILQ_INIT(&(list)); \
}
#define PIF_QUEUE_REINIT(list) \
{ \
while (!LIST_EMPTY(&(list))) { \
@ -93,16 +108,42 @@
LIST_INIT(&(list)); \
}
void mlacp_local_lif_clear_pending_mac(struct CSM* csm, struct LocalInterface *local_lif);
/*****************************************
* Rb tree Functions
*
* ***************************************/
static int MACMsg_compare(const struct MACMsg *mac1, const struct MACMsg *mac2)
{
if (mac1->vid < mac2->vid)
return -1;
if (mac1->vid > mac2->vid)
return 1;
if(memcmp((char *)&mac1->mac_addr, (char *)&mac2->mac_addr, ETHER_ADDR_LEN) < 0)
return -1;
if(memcmp((char *)&mac1->mac_addr, (char *)&mac2->mac_addr, ETHER_ADDR_LEN) > 0)
return 1;
return 0;
}
RB_GENERATE(mac_rb_tree, MACMsg, mac_entry_rb, MACMsg_compare);
#define WARM_REBOOT_TIMEOUT 90
#define PEER_REBOOT_TIMEOUT 300
/*****************************************
* Static Function
*
* ***************************************/
static char *mlacp_state(struct CSM* csm);
char *mlacp_state(struct CSM* csm);
static void mlacp_resync_arp(struct CSM* csm);
static void mlacp_resync_ndisc(struct CSM *csm);
static void mlacp_resync_mac(struct CSM* csm);
/* Sync Sender APIs*/
static void mlacp_sync_send_sysConf(struct CSM* csm);
static void mlacp_sync_send_aggConf(struct CSM* csm);
@ -138,6 +179,15 @@ static void mlacp_stage_sync_request_handler(struct CSM* csm, struct Msg* msg);
static void mlacp_stage_handler(struct CSM* csm, struct Msg* msg);
static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg);
void mlacp_local_lif_state_mac_handler(struct CSM* csm);
/* Interface up ack */
static void mlacp_fsm_send_if_up_ack(
struct CSM *csm,
uint8_t if_type,
uint16_t if_id,
uint8_t port_isolation_enable);
/******************************************************************
* Sync Sender APIs
*
@ -210,19 +260,35 @@ static void mlacp_sync_send_aggState(struct CSM* csm)
static void mlacp_sync_send_syncMacInfo(struct CSM* csm)
{
int msg_len = 0;
struct Msg* msg = NULL;
struct MACMsg* mac_msg = NULL;
struct MACMsg mac_find;
int count = 0;
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
memset(&mac_find, 0, sizeof(struct MACMsg));
while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list)))
{
msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list));
TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail);
msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf, count);
mac_msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list));
MAC_TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), mac_msg, tail);
msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, mac_msg, count);
count++;
free(msg->buf);
free(msg);
//free mac_msg if marked for delete.
if (mac_msg->op_type == MAC_SYNC_DEL)
{
if (!(mac_msg->mac_entry_rb.rbt_parent))
{
//If the entry is parent then the parent pointer would be null
//search to confirm if the MAC is present in RB tree. if not then free.
mac_find.vid = mac_msg->vid ;
memcpy(mac_find.mac_addr, mac_msg->mac_addr, ETHER_ADDR_LEN);
if (!RB_FIND(mac_rb_tree, &MLACP(csm).mac_rb ,&mac_find))
free(mac_msg);
}
}
if (count >= MAX_MAC_ENTRY_NUM)
{
iccp_csm_send(csm, g_csm_buf, msg_len);
@ -251,7 +317,7 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm)
msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list));
TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail);
msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf, count);
msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf, count, NEIGH_SYNC_CLIENT_IP);
count++;
free(msg->buf);
free(msg);
@ -283,7 +349,7 @@ static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
msg = TAILQ_FIRST(&(MLACP(csm).ndisc_msg_list));
TAILQ_REMOVE(&(MLACP(csm).ndisc_msg_list), msg, tail);
msg_len = mlacp_prepare_for_ndisc_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct NDISCMsg *)msg->buf, count);
msg_len = mlacp_prepare_for_ndisc_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct NDISCMsg *)msg->buf, count, NEIGH_SYNC_CLIENT_IP);
count++;
free(msg->buf);
free(msg);
@ -301,6 +367,7 @@ static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
return;
}
static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm)
{
struct System* sys = NULL;
@ -348,7 +415,7 @@ static void mlacp_sync_send_heartbeat(struct CSM* csm)
int msg_len = 0;
if ((csm->heartbeat_send_time == 0) ||
((time(NULL) - csm->heartbeat_send_time) > 1))
((time(NULL) - csm->heartbeat_send_time) > csm->keepalive_time))
{
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
msg_len = mlacp_prepare_for_heartbeat(csm, g_csm_buf, CSM_BUFFER_SIZE);
@ -386,8 +453,15 @@ static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg)
if (mlacp_fsm_update_system_conf(csm, sysconf) == MCLAG_ERROR)
{
/*NOTE: we just change the node ID local side without sending NAK msg*/
ICCPD_LOG_WARN(__FUNCTION__, "Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id);
ICCPD_LOG_DEBUG("ICCP_FSM", "RX same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id);
mlacp_sync_send_nak_handler(csm, msg);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
sysconf->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
}
else
{
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
sysconf->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
}
return;
@ -419,6 +493,13 @@ static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg)
if (mlacp_fsm_update_Agg_conf(csm, portconf) == MCLAG_ERROR)
{
mlacp_sync_send_nak_handler(csm, msg);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
}
else
{
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
}
return;
@ -433,7 +514,22 @@ static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg)
{
mlacp_sync_send_nak_handler(csm, msg);
/*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/
return;
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
portstate->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
}
else
{
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
portstate->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
}
/* Send interface up ack for MLAG interface regardless of the
* processing return code
*/
if (portstate->agg_state == PORT_STATE_UP)
{
mlacp_fsm_send_if_up_ack(
csm, IF_UP_ACK_TYPE_PORT_CHANNEL, ntohs(portstate->agg_id),
PORT_ISOLATION_STATE_ENABLE);
}
return;
@ -448,7 +544,12 @@ static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg)
{
/* Sync done*/
MLACP(csm).wait_for_sync_data = 0;
ICCPD_LOG_DEBUG("ICCP_FSM", "RX sync done");
}
else
ICCPD_LOG_DEBUG("ICCP_FSM", "RX sync start");
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
syncdata->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
@ -460,8 +561,13 @@ static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg)
mlacp_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)];
MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num);
ICCPD_LOG_DEBUG("ICCP_FSM", "RX sync_requrest: req_no %d",
MLACP(csm).sync_req_num);
/* Reply the peer all sync info*/
mlacp_sync_send_all_info_handler(csm);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
mlacp_sync_req->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
@ -474,6 +580,13 @@ static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg)
if (mlacp_fsm_update_port_channel_info(csm, portconf) == MCLAG_ERROR)
{
mlacp_sync_send_nak_handler(csm, msg);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
}
else
{
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
}
return;
@ -485,6 +598,8 @@ static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg)
peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_peerlink_info( csm, peerlink);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
peerlink->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
@ -495,6 +610,8 @@ static void mlacp_sync_recv_macInfo(struct CSM* csm, struct Msg* msg)
mac_info = (struct mLACPMACInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_mac_info_from_peer(csm, mac_info);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
mac_info->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
@ -505,6 +622,8 @@ static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg)
arp_info = (struct mLACPARPInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_arp_info(csm, arp_info);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
arp_info->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
@ -518,6 +637,7 @@ static void mlacp_sync_recv_ndiscInfo(struct CSM *csm, struct Msg *msg)
return;
}
static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg)
{
/*Don't support currently*/
@ -530,6 +650,8 @@ static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg)
tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_heartbeat(csm, tlv);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
@ -540,10 +662,102 @@ static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg)
tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_warmboot(csm, tlv);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return;
}
static void mlacp_fsm_recv_if_up_ack(struct CSM* csm, struct Msg* msg)
{
struct mLACPIfUpAckTLV *tlv = NULL;
struct LocalInterface *local_if = NULL;
uint16_t if_id;
tlv = (struct mLACPIfUpAckTLV *)(&msg->buf[sizeof(ICCHdr)]);
if (tlv == NULL)
return;
if_id = ntohs(tlv->if_id);
if (tlv->if_type == IF_UP_ACK_TYPE_PORT_CHANNEL)
{
local_if = local_if_find_by_po_id(if_id);
ICCPD_LOG_DEBUG("ICCP_FSM",
"RX if_up_ack: po_id %d, local if 0x%x, active %u",
if_id, local_if, local_if ? local_if->po_active : 0);
/* Ignore the ack if MLAG interface has gone down */
if (local_if && local_if->po_active)
mlacp_link_enable_traffic_distribution(local_if);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
}
else
{
ICCPD_LOG_ERR("ICCP_FSM", "RX if_up_ack: invalid i/f type %u, i/f ID %u",
tlv->if_type, if_id);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
}
}
void mlacp_local_lif_state_mac_handler(struct CSM* csm)
{
struct LocalInterface* local_if = NULL;
LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next)
{
if ((local_if->state == PORT_STATE_DOWN) && (local_if->type == IF_T_PORT_CHANNEL))
{
// clear the pending macs if timer is expired.
if (local_if->po_down_time && ((time(NULL) - local_if->po_down_time) > MLACP_LOCAL_IF_DOWN_TIMER))
{
mlacp_local_lif_clear_pending_mac(csm, local_if);
local_if->po_down_time = 0;
}
}
}
}
void mlacp_peer_link_learning_handler(struct CSM* csm)
{
if (csm->peer_link_if == NULL)
return;
if (csm->peer_link_if->vlan_count == 0) {
return;
}
if (csm->peer_link_learning_retry_time && ((time(NULL) - csm->peer_link_learning_retry_time) > 2))
{
ICCPD_LOG_DEBUG(__FUNCTION__, "peer_link_learning_enable %d", csm->peer_link_learning_enable);
set_peerlink_learn_kernel(csm, csm->peer_link_learning_enable, 10);
}
}
void mlacp_mac_msg_queue_reinit(struct CSM* csm)
{
struct MACMsg* mac_msg = NULL;
MLACP_MAC_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
ICCPD_LOG_NOTICE("ICCP_FDB", "mlacp_mac_msg_queue_reinit clear mac_msg_list pointers in existing MAC entries");
// unset the mac_msg_list pointers for existing MAC entries.
RB_FOREACH (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb)
{
if (MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
{
CLEAR_MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail);
}
}
return;
}
/*****************************************
* MLACP Init
*
@ -563,7 +777,8 @@ void mlacp_init(struct CSM* csm, int all)
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
mlacp_mac_msg_queue_reinit(csm);
PIF_QUEUE_REINIT(MLACP(csm).pif_list);
LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list);
@ -572,7 +787,7 @@ void mlacp_init(struct CSM* csm, int all)
/* if no clean all, keep the arp info & local interface info for next connection*/
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list);
RB_INIT(mac_rb_tree, &MLACP(csm).mac_rb );
LIF_QUEUE_REINIT(MLACP(csm).lif_list);
MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK;
@ -596,10 +811,11 @@ void mlacp_finalize(struct CSM* csm)
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
mlacp_mac_msg_queue_reinit(csm);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list);
RB_INIT(mac_rb_tree, &MLACP(csm).mac_rb );
/* remove lif & lif-purge queue */
LIF_QUEUE_REINIT(MLACP(csm).lif_list);
@ -637,8 +853,14 @@ void mlacp_fsm_transit(struct CSM* csm)
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
mlacp_mac_msg_queue_reinit(csm);
MLACP(csm).current_state = MLACP_STATE_INIT;
if (csm->sock_fd > 0)
{
/* Close CSM socket and reset its value */
scheduler_csm_socket_cleanup(csm, 2);
SYSTEM_INCR_SOCKET_CLEANUP_COUNTER(system_get_instance());
}
}
return;
}
@ -657,6 +879,9 @@ void mlacp_fsm_transit(struct CSM* csm)
mlacp_sync_send_heartbeat(csm);
mlacp_local_lif_state_mac_handler(csm);
mlacp_peer_link_learning_handler(csm);
/* Dequeue msg if any*/
while (have_msg)
{
@ -728,7 +953,7 @@ void mlacp_fsm_transit(struct CSM* csm)
}
/* Helper function for dumping application state machine */
static char* mlacp_state(struct CSM* csm)
char* mlacp_state(struct CSM* csm)
{
if (csm == NULL )
return "MLACP_NULL";
@ -767,12 +992,6 @@ void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg)
if (msg == NULL )
return;
#if 0
icc_hdr = (ICCHdr*)msg->buf;
icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)];
ICCPD_LOG_DEBUG("mlacp_fsm", " mLACP enqueue: tlv = 0x%04x", icc_param->type);
#endif
TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail);
return;
@ -792,32 +1011,77 @@ struct Msg* mlacp_dequeue_msg(struct CSM* csm)
return msg;
}
/******************************************
* When peerlink ready, prepare the MACMsg
*
******************************************/
static void mlacp_resync_mac(struct CSM* csm)
void mlacp_sync_mac(struct CSM* csm)
{
struct Msg* msg = NULL;
struct MACMsg* mac_msg = NULL;
struct Msg *msg_send = NULL;
/* recover MAC info sync from peer*/
if (!TAILQ_EMPTY(&(MLACP(csm).mac_list)))
RB_FOREACH (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb)
{
TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail)
/*If MAC with local age flag, dont sync to peer. Such MAC only exist when peer is warm-reboot.
If peer is warm-reboot, peer age flag is not set when connection is lost.
When MAC is aged in local switch, this MAC is not deleted for no peer age flag.
After warm-reboot, this MAC must be learnt by peer and sync to local switch*/
if (!(mac_msg->age_flag & MAC_AGE_LOCAL))
{
mac_msg = (struct MACMsg*)msg->buf;
mac_msg->op_type = MAC_SYNC_ADD;
if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0)
//As part of local sync do not delete peer age
//mac_msg->age_flag &= ~MAC_AGE_PEER;
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
{
mac_msg->age_flag &= ~MAC_AGE_PEER;
TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail);
ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d",
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);
TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), mac_msg, tail);
}
ICCPD_LOG_DEBUG("ICCP_FDB", "Sync MAC: MAC-msg-list enqueue interface %s, "
"MAC %s vlan %d, age_flag %d", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->age_flag);
}
else
{
/*If MAC with local age flag and is point to MCLAG enabled port, reomove local age flag*/
if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)
{
ICCPD_LOG_DEBUG("ICCP_FDB", "Sync MAC: MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, age_flag %d",
mac_msg->ifname, mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->age_flag);
/* After warmboot remote mac can exist, should not
update existing flag
*/
//mac_msg->age_flag &= ~MAC_AGE_LOCAL;
}
}
}
return;
}
void mlacp_local_lif_clear_pending_mac(struct CSM* csm, struct LocalInterface *local_lif)
{
ICCPD_LOG_DEBUG("ICCP_FDB", "mlacp_local_lif_clear_pending_mac If: %s ", local_lif->name );
struct MACMsg* mac_msg = NULL, *mac_temp = NULL;
RB_FOREACH_SAFE (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb, mac_temp)
{
if (mac_msg->pending_local_del && strcmp(mac_msg->origin_ifname, local_lif->name) == 0)
{
ICCPD_LOG_DEBUG("ICCP_FDB", "Clear pending MAC: MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, age_flag %d, remove local age flag",
mac_msg->ifname, mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->age_flag);
del_mac_from_chip(mac_msg);
// if static dont delete mac
if (mac_msg->fdb_type != MAC_TYPE_STATIC)
{
//TBD do we need to send delete notification to peer .?
MAC_RB_REMOVE(mac_rb_tree, &MLACP(csm).mac_rb, mac_msg);
mac_msg->op_type = MAC_SYNC_DEL;
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
{
free(mac_msg);
}
}
else
mac_msg->pending_local_del = 0;
}
}
return;
}
/******************************************
@ -837,6 +1101,7 @@ static void mlacp_resync_arp(struct CSM* csm)
{
arp_msg = (struct ARPMsg*)msg->buf;
arp_msg->op_type = NEIGH_SYNC_ADD;
arp_msg->flag = 0;
if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0)
{
TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail);
@ -862,6 +1127,7 @@ static void mlacp_resync_ndisc(struct CSM *csm)
{
ndisc_msg = (struct NDISCMsg *)msg->buf;
ndisc_msg->op_type = NEIGH_SYNC_ADD;
ndisc_msg->flag = 0;
if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, sizeof(struct NDISCMsg)) == 0)
{
TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail);
@ -1016,6 +1282,15 @@ static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg)
case TLV_T_MLACP_WARMBOOT_FLAG:
mlacp_sync_recv_warmboot(csm, msg);
break;
case TLV_T_MLACP_IF_UP_ACK:
mlacp_fsm_recv_if_up_ack(csm, msg);
break;
default:
ICCPD_LOG_ERR("ICCP_FSM", "Receive unsupported msg 0x%x from peer",
icc_param->type);
break;
}
/*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/
@ -1238,14 +1513,24 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
iccp_csm_send(csm, g_csm_buf, len);
/* Destroy old interface*/
if (lif_purge != NULL)
{
/* Re-enable traffic distribution on MCLAG interface */
if ((lif_purge->type == IF_T_PORT_CHANNEL) && lif_purge->is_traffic_disable)
mlacp_link_enable_traffic_distribution(lif_purge);
LIST_REMOVE(lif_purge, mlacp_purge_next);
}
}
/* Send mlag lif*/
LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next)
{
if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync)
{
/* Disable traffic distribution on LAG members if LAG is down */
if (!lif->po_active)
mlacp_link_disable_traffic_distribution(lif);
/* Send port channel information*/
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif, 0);
@ -1264,10 +1549,14 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
/* Send port channel state information*/
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif);
iccp_csm_send(csm, g_csm_buf, len);
//if po state send to peer is not successful, next time will try to
//send again, until then dont unmark lif->changed flag
if (iccp_csm_send(csm, g_csm_buf, len) > 0)
{
lif->changed = 0;
}
}
}
/* Send MAC info if any*/
mlacp_sync_send_syncMacInfo(csm);
@ -1291,3 +1580,90 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
return;
}
/*****************************************
* Interface up ACK
*
****************************************/
static void mlacp_fsm_send_if_up_ack(
struct CSM *csm,
uint8_t if_type,
uint16_t if_id,
uint8_t port_isolation_enable)
{
struct System* sys = NULL;
int msg_len = 0;
int rc = -10;
sys = system_get_instance();
if (sys == NULL)
return;
/* Interface up ACK is expected only after the interface is up */
if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE)
return;
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
msg_len = mlacp_prepare_for_if_up_ack(
csm, g_csm_buf, CSM_BUFFER_SIZE, if_type, if_id, port_isolation_enable);
if (msg_len > 0)
rc = iccp_csm_send(csm, g_csm_buf, msg_len);
if (rc <= 0)
{
ICCPD_LOG_ERR(__FUNCTION__, "failed, interface type/id %d/%d, rc %d",
if_type, if_id, rc);
}
else
{
ICCPD_LOG_DEBUG(__FUNCTION__,"interface type/id %d/%d", if_type, if_id);
}
}
/* MLACP ICCP mesage type to debug counter type conversion */
ICCP_DBG_CNTR_MSG_e mlacp_fsm_iccp_to_dbg_msg_type(uint32_t tlv_type)
{
switch (tlv_type)
{
case TLV_T_MLACP_SYSTEM_CONFIG:
return ICCP_DBG_CNTR_MSG_SYS_CONFIG;
case TLV_T_MLACP_AGGREGATOR_CONFIG:
return ICCP_DBG_CNTR_MSG_AGGR_CONFIG;
case TLV_T_MLACP_AGGREGATOR_STATE:
return ICCP_DBG_CNTR_MSG_AGGR_STATE;
case TLV_T_MLACP_SYNC_REQUEST:
return ICCP_DBG_CNTR_MSG_SYNC_REQ;
case TLV_T_MLACP_SYNC_DATA:
return ICCP_DBG_CNTR_MSG_SYNC_DATA;
case TLV_T_MLACP_HEARTBEAT:
return ICCP_DBG_CNTR_MSG_HEART_BEAT;
case TLV_T_MLACP_PORT_CHANNEL_INFO:
return ICCP_DBG_CNTR_MSG_PORTCHANNEL_INFO;
case TLV_T_MLACP_PEERLINK_INFO:
return ICCP_DBG_CNTR_MSG_PEER_LINK_INFO;
case TLV_T_MLACP_ARP_INFO:
return ICCP_DBG_CNTR_MSG_ARP_INFO;
case TLV_T_MLACP_MAC_INFO:
return ICCP_DBG_CNTR_MSG_MAC_INFO;
case TLV_T_MLACP_WARMBOOT_FLAG:
return ICCP_DBG_CNTR_MSG_WARM_BOOT;
case TLV_T_MLACP_IF_UP_ACK:
return ICCP_DBG_CNTR_MSG_IF_UP_ACK;
default:
ICCPD_LOG_DEBUG(__FUNCTION__, "No debug counter for TLV type %u",
tlv_type);
return ICCP_DBG_CNTR_MSG_MAX;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -91,6 +91,10 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu
tlv->port_num_agg_id = 0;
tlv->actor_key = 0;
ICCPD_LOG_DEBUG("ICCP_FSM", "TX sync_request: role %s, sync_state %s",
(csm->role_type == STP_ROLE_STANDBY) ? "standby" : "active",
mlacp_state(csm));
return msg_len;
}
@ -138,6 +142,7 @@ int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_s
else
tlv->flags = htons(0x01);
ICCPD_LOG_DEBUG("ICCP_CSM", "TX sync %s", end ? "end" : "start");
return msg_len;
}
@ -182,6 +187,10 @@ int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size
memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN);
tlv->sys_priority = htons(MLACP(csm).system_priority);
tlv->node_id = MLACP(csm).node_id;
ICCPD_LOG_DEBUG("ICCP_FSM", "TX sys_config: systemID %s, priority %u, nodeID %u",
mac_addr_to_str(MLACP(csm).system_id), MLACP(csm).system_priority,
MLACP(csm).node_id);
return msg_len;
}
@ -232,6 +241,8 @@ int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_s
tlv->actor_key = 0;
tlv->agg_state = local_if->state;
ICCPD_LOG_DEBUG("ICCP_FSM", "TX aggrport_state: %s is %s",
local_if->name, (local_if->state == PORT_STATE_UP) ? "up" : "down");
return msg_len;
}
@ -280,6 +291,8 @@ int mlacp_prepare_for_Aggport_config(struct CSM* csm,
memcpy(tlv->agg_name, lif->name, MAX_L_PORT_NAME);
memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN);
ICCPD_LOG_DEBUG("ICCP_FSM", "TX aggrport_config: %s, purge_flag %d, mac %s",
lif->name, purge_flag, mac_addr_to_str(lif->mac_addr));
return msg_len;
}
@ -322,12 +335,13 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu
MacData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * count];
MacData->type = mac_msg->op_type;
sprintf(MacData->mac_str, "%s", mac_msg->mac_str);
MacData->mac_type = mac_msg->fdb_type;
memcpy(MacData->mac_addr, mac_msg->mac_addr,ETHER_ADDR_LEN);
sprintf(MacData->ifname, "%s", mac_msg->origin_ifname);
MacData->vid = htons(mac_msg->vid);
ICCPD_LOG_NOTICE(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname,
mac_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count);
ICCPD_LOG_DEBUG("ICCP_FDB", "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count);
return msg_len;
}
@ -336,7 +350,7 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu
* Preprare Sync ARP-Info TLV
*
* ***************************************/
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count)
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count, int dir)
{
struct mLACPARPInfoTLV* tlv = NULL;
size_t msg_len = 0;
@ -373,13 +387,15 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size,
ArpData = (struct ARPMsg *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * count];
ArpData->op_type = arp_msg->op_type;
ArpData->flag = arp_msg->flag;
sprintf(ArpData->ifname, "%s", arp_msg->ifname);
ArpData->ipv4_addr = arp_msg->ipv4_addr;
memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN);
ICCPD_LOG_NOTICE(__FUNCTION__, "Send ARP messge to peer, if name %s mac %02x:%02x:%02x:%02x:%02x:%02x IP %s", ArpData->ifname, ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2],
ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5], show_ip_str(ArpData->ipv4_addr));
ICCPD_LOG_DEBUG(__FUNCTION__, "Send ARP messge to peer, dir %d, flag %d, if name %s mac %02x:%02x:%02x:%02x:%02x:%02x IP %s",
dir, ArpData->flag, ArpData->ifname,
ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2], ArpData->mac_addr[3], ArpData->mac_addr[4],
ArpData->mac_addr[5], show_ip_str(ArpData->ipv4_addr));
return msg_len;
}
@ -387,14 +403,13 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size,
* Preprare Sync NDISC-Info TLV
*
* ***************************************/
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count)
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count, int dir)
{
struct mLACPNDISCInfoTLV *tlv = NULL;
size_t msg_len = 0;
size_t tlv_len = 0;
ICCHdr *icc_hdr = NULL;
struct NDISCMsg *NdiscData;
struct NDISCMsg *NdiscData = NULL;
if (!csm)
return -1;
@ -422,14 +437,16 @@ int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size
tlv->icc_parameter.type = htons(TLV_T_MLACP_NDISC_INFO);
}
NdiscData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * count];
NdiscData = (struct NDISCMsg *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * count];
NdiscData->op_type = ndisc_msg->op_type;
NdiscData->flag = ndisc_msg->flag;
sprintf(NdiscData->ifname, "%s", ndisc_msg->ifname);
memcpy(NdiscData->ipv6_addr, ndisc_msg->ipv6_addr, 32);
memcpy(NdiscData->ipv6_addr, ndisc_msg->ipv6_addr, 16);
memcpy(NdiscData->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN);
ICCPD_LOG_NOTICE(__FUNCTION__, "Send ND messge to peer, if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x IPv6 %s", NdiscData->ifname,
ICCPD_LOG_DEBUG(__FUNCTION__, "Send ND messge to peer, dir %d, flag %d, if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x IPv6 %s",
dir, NdiscData->flag, NdiscData->ifname,
NdiscData->mac_addr[0], NdiscData->mac_addr[1], NdiscData->mac_addr[2], NdiscData->mac_addr[3], NdiscData->mac_addr[4],
NdiscData->mac_addr[5], show_ipv6_str((char *)NdiscData->ipv6_addr));
@ -465,7 +482,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf,
return MCLAG_ERROR;
/* Calculate VLAN ID Length */
LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next)
RB_FOREACH(vlan_id, vlan_rb_tree, &(port_channel->vlan_tree))
if (vlan_id != NULL)
num_of_vlan_id++;
@ -500,7 +517,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf,
tlv->num_of_vlan_id = htons(num_of_vlan_id);
num_of_vlan_id = 0;
LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next)
RB_FOREACH(vlan_id, vlan_rb_tree, &(port_channel->vlan_tree))
{
if (vlan_id != NULL )
{
@ -512,7 +529,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf,
}
ICCPD_LOG_DEBUG(__FUNCTION__, "PortChannel%d: ipv4 addr = %s l3 mode %d", port_channel->po_id, show_ip_str( tlv->ipv4_addr), tlv->l3_mode);
ICCPD_LOG_DEBUG("ICCP_FSM", "TX po_info: %s has %d vlans", port_channel->name, num_of_vlan_id);
return msg_len;
}
@ -562,8 +579,8 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf,
memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME);
tlv->port_type = peerlink_port->type;
ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port is %s, type = %d", tlv->if_name, tlv->port_type);
ICCPD_LOG_DEBUG("ICCP_FSM", "TX peerlink_info: name %s, type %d",
peerlink_port->name, peerlink_port->type);
return msg_len;
}
@ -649,8 +666,60 @@ int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_siz
tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter));
tlv->warmboot = 0x1;
ICCPD_LOG_DEBUG("ICCP_FSM", "TX start warm reboot");
return msg_len;
}
ICCPD_LOG_NOTICE(__FUNCTION__, "Send warm reboot notification to peer!");
/*****************************************
* Prepare interface up ACK message
*
* ***************************************/
int mlacp_prepare_for_if_up_ack(
struct CSM *csm,
char *buf,
size_t max_buf_size,
uint8_t if_type,
uint16_t if_id,
uint8_t port_isolation_state)
{
struct System* sys = NULL;
ICCHdr* icc_hdr = (ICCHdr*) buf;
struct mLACPIfUpAckTLV* tlv = (struct mLACPIfUpAckTLV*) &buf[sizeof(ICCHdr)];
size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPIfUpAckTLV);
if(csm == NULL)
return -1;
if(buf == NULL)
return -1;
if(msg_len > max_buf_size)
return -1;
if((sys = system_get_instance()) == NULL)
return -1;
/* Prepare for sync request */
memset(buf, 0, max_buf_size);
icc_hdr = (ICCHdr*) buf;
tlv = (struct mLACPIfUpAckTLV*) &buf[sizeof(ICCHdr)];
/* ICC header */
mlacp_fill_icc_header(csm, icc_hdr, msg_len);
/* If up ack TLV */
tlv->icc_parameter.u_bit = 0;
tlv->icc_parameter.f_bit = 0;
tlv->icc_parameter.type = htons(TLV_T_MLACP_IF_UP_ACK);
tlv->icc_parameter.len = htons(sizeof(struct mLACPIfUpAckTLV) - sizeof(ICCParameter));
tlv->if_type = if_type;
tlv->if_id = htons(if_id);
tlv->port_isolation_state = port_isolation_state;
ICCPD_LOG_DEBUG("ICCP_FSM", "TX if_up_ack: PortChannel%d, isolation_set %d",
if_id, port_isolation_state);
return msg_len;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,618 @@
/* $OpenBSD: subr_tree.c,v 1.9 2017/06/08 03:30:52 dlg Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <../include/openbsd_tree.h>
static inline struct rb_entry *rb_n2e(const struct rb_type *t, void *node)
{
unsigned long addr = (unsigned long)node;
return ((struct rb_entry *)(addr + t->t_offset));
}
static inline void *rb_e2n(const struct rb_type *t, struct rb_entry *rbe)
{
unsigned long addr = (unsigned long)rbe;
return ((void *)(addr - t->t_offset));
}
#define RBE_LEFT(_rbe) (_rbe)->rbt_left
#define RBE_RIGHT(_rbe) (_rbe)->rbt_right
#define RBE_PARENT(_rbe) (_rbe)->rbt_parent
#define RBE_COLOR(_rbe) (_rbe)->rbt_color
#define RBH_ROOT(_rbt) (_rbt)->rbt_root
static inline void rbe_set(struct rb_entry *rbe, struct rb_entry *parent)
{
RBE_PARENT(rbe) = parent;
RBE_LEFT(rbe) = RBE_RIGHT(rbe) = NULL;
RBE_COLOR(rbe) = RB_RED;
}
static inline void rbe_set_blackred(struct rb_entry *black,
struct rb_entry *red)
{
RBE_COLOR(black) = RB_BLACK;
RBE_COLOR(red) = RB_RED;
}
static inline void rbe_augment(const struct rb_type *t, struct rb_entry *rbe)
{
(*t->t_augment)(rb_e2n(t, rbe));
}
static inline void rbe_if_augment(const struct rb_type *t, struct rb_entry *rbe)
{
if (t->t_augment != NULL)
rbe_augment(t, rbe);
}
static inline void rbe_rotate_left(const struct rb_type *t,
struct rbt_tree *rbt, struct rb_entry *rbe)
{
struct rb_entry *parent;
struct rb_entry *tmp;
tmp = RBE_RIGHT(rbe);
RBE_RIGHT(rbe) = RBE_LEFT(tmp);
if (RBE_RIGHT(rbe) != NULL)
RBE_PARENT(RBE_LEFT(tmp)) = rbe;
parent = RBE_PARENT(rbe);
RBE_PARENT(tmp) = parent;
if (parent != NULL) {
if (rbe == RBE_LEFT(parent))
RBE_LEFT(parent) = tmp;
else
RBE_RIGHT(parent) = tmp;
} else
RBH_ROOT(rbt) = tmp;
RBE_LEFT(tmp) = rbe;
RBE_PARENT(rbe) = tmp;
if (t->t_augment != NULL) {
rbe_augment(t, rbe);
rbe_augment(t, tmp);
parent = RBE_PARENT(tmp);
if (parent != NULL)
rbe_augment(t, parent);
}
}
static inline void rbe_rotate_right(const struct rb_type *t,
struct rbt_tree *rbt, struct rb_entry *rbe)
{
struct rb_entry *parent;
struct rb_entry *tmp;
tmp = RBE_LEFT(rbe);
RBE_LEFT(rbe) = RBE_RIGHT(tmp);
if (RBE_LEFT(rbe) != NULL)
RBE_PARENT(RBE_RIGHT(tmp)) = rbe;
parent = RBE_PARENT(rbe);
RBE_PARENT(tmp) = parent;
if (parent != NULL) {
if (rbe == RBE_LEFT(parent))
RBE_LEFT(parent) = tmp;
else
RBE_RIGHT(parent) = tmp;
} else
RBH_ROOT(rbt) = tmp;
RBE_RIGHT(tmp) = rbe;
RBE_PARENT(rbe) = tmp;
if (t->t_augment != NULL) {
rbe_augment(t, rbe);
rbe_augment(t, tmp);
parent = RBE_PARENT(tmp);
if (parent != NULL)
rbe_augment(t, parent);
}
}
static inline void rbe_insert_color(const struct rb_type *t,
struct rbt_tree *rbt, struct rb_entry *rbe)
{
struct rb_entry *parent, *gparent, *tmp;
while ((parent = RBE_PARENT(rbe)) != NULL
&& RBE_COLOR(parent) == RB_RED) {
gparent = RBE_PARENT(parent);
if (parent == RBE_LEFT(gparent)) {
tmp = RBE_RIGHT(gparent);
if (tmp != NULL && RBE_COLOR(tmp) == RB_RED) {
RBE_COLOR(tmp) = RB_BLACK;
rbe_set_blackred(parent, gparent);
rbe = gparent;
continue;
}
if (RBE_RIGHT(parent) == rbe) {
rbe_rotate_left(t, rbt, parent);
tmp = parent;
parent = rbe;
rbe = tmp;
}
rbe_set_blackred(parent, gparent);
rbe_rotate_right(t, rbt, gparent);
} else {
tmp = RBE_LEFT(gparent);
if (tmp != NULL && RBE_COLOR(tmp) == RB_RED) {
RBE_COLOR(tmp) = RB_BLACK;
rbe_set_blackred(parent, gparent);
rbe = gparent;
continue;
}
if (RBE_LEFT(parent) == rbe) {
rbe_rotate_right(t, rbt, parent);
tmp = parent;
parent = rbe;
rbe = tmp;
}
rbe_set_blackred(parent, gparent);
rbe_rotate_left(t, rbt, gparent);
}
}
RBE_COLOR(RBH_ROOT(rbt)) = RB_BLACK;
}
static inline void rbe_remove_color(const struct rb_type *t,
struct rbt_tree *rbt,
struct rb_entry *parent,
struct rb_entry *rbe)
{
struct rb_entry *tmp;
while ((rbe == NULL || RBE_COLOR(rbe) == RB_BLACK)
&& rbe != RBH_ROOT(rbt) && parent) {
if (RBE_LEFT(parent) == rbe) {
tmp = RBE_RIGHT(parent);
if (RBE_COLOR(tmp) == RB_RED) {
rbe_set_blackred(tmp, parent);
rbe_rotate_left(t, rbt, parent);
tmp = RBE_RIGHT(parent);
}
if ((RBE_LEFT(tmp) == NULL
|| RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK)
&& (RBE_RIGHT(tmp) == NULL
|| RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
RBE_COLOR(tmp) = RB_RED;
rbe = parent;
parent = RBE_PARENT(rbe);
} else {
if (RBE_RIGHT(tmp) == NULL
|| RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK) {
struct rb_entry *oleft;
oleft = RBE_LEFT(tmp);
if (oleft != NULL)
RBE_COLOR(oleft) = RB_BLACK;
RBE_COLOR(tmp) = RB_RED;
rbe_rotate_right(t, rbt, tmp);
tmp = RBE_RIGHT(parent);
}
RBE_COLOR(tmp) = RBE_COLOR(parent);
RBE_COLOR(parent) = RB_BLACK;
if (RBE_RIGHT(tmp))
RBE_COLOR(RBE_RIGHT(tmp)) = RB_BLACK;
rbe_rotate_left(t, rbt, parent);
rbe = RBH_ROOT(rbt);
break;
}
} else {
tmp = RBE_LEFT(parent);
if (RBE_COLOR(tmp) == RB_RED) {
rbe_set_blackred(tmp, parent);
rbe_rotate_right(t, rbt, parent);
tmp = RBE_LEFT(parent);
}
if ((RBE_LEFT(tmp) == NULL
|| RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK)
&& (RBE_RIGHT(tmp) == NULL
|| RBE_COLOR(RBE_RIGHT(tmp)) == RB_BLACK)) {
RBE_COLOR(tmp) = RB_RED;
rbe = parent;
parent = RBE_PARENT(rbe);
} else {
if (RBE_LEFT(tmp) == NULL
|| RBE_COLOR(RBE_LEFT(tmp)) == RB_BLACK) {
struct rb_entry *oright;
oright = RBE_RIGHT(tmp);
if (oright != NULL)
RBE_COLOR(oright) = RB_BLACK;
RBE_COLOR(tmp) = RB_RED;
rbe_rotate_left(t, rbt, tmp);
tmp = RBE_LEFT(parent);
}
RBE_COLOR(tmp) = RBE_COLOR(parent);
RBE_COLOR(parent) = RB_BLACK;
if (RBE_LEFT(tmp) != NULL)
RBE_COLOR(RBE_LEFT(tmp)) = RB_BLACK;
rbe_rotate_right(t, rbt, parent);
rbe = RBH_ROOT(rbt);
break;
}
}
}
if (rbe != NULL)
RBE_COLOR(rbe) = RB_BLACK;
}
static inline struct rb_entry *
rbe_remove(const struct rb_type *t, struct rbt_tree *rbt, struct rb_entry *rbe)
{
struct rb_entry *child, *parent, *old = rbe;
unsigned int color;
if (RBE_LEFT(rbe) == NULL)
child = RBE_RIGHT(rbe);
else if (RBE_RIGHT(rbe) == NULL)
child = RBE_LEFT(rbe);
else {
struct rb_entry *tmp;
rbe = RBE_RIGHT(rbe);
while ((tmp = RBE_LEFT(rbe)) != NULL)
rbe = tmp;
child = RBE_RIGHT(rbe);
parent = RBE_PARENT(rbe);
color = RBE_COLOR(rbe);
if (child != NULL)
RBE_PARENT(child) = parent;
if (parent != NULL) {
if (RBE_LEFT(parent) == rbe)
RBE_LEFT(parent) = child;
else
RBE_RIGHT(parent) = child;
rbe_if_augment(t, parent);
} else
RBH_ROOT(rbt) = child;
if (RBE_PARENT(rbe) == old)
parent = rbe;
*rbe = *old;
tmp = RBE_PARENT(old);
if (tmp != NULL) {
if (RBE_LEFT(tmp) == old)
RBE_LEFT(tmp) = rbe;
else
RBE_RIGHT(tmp) = rbe;
rbe_if_augment(t, tmp);
} else
RBH_ROOT(rbt) = rbe;
RBE_PARENT(RBE_LEFT(old)) = rbe;
if (RBE_RIGHT(old))
RBE_PARENT(RBE_RIGHT(old)) = rbe;
if (t->t_augment != NULL && parent != NULL) {
tmp = parent;
do {
rbe_augment(t, tmp);
tmp = RBE_PARENT(tmp);
} while (tmp != NULL);
}
goto color;
}
parent = RBE_PARENT(rbe);
color = RBE_COLOR(rbe);
if (child != NULL)
RBE_PARENT(child) = parent;
if (parent != NULL) {
if (RBE_LEFT(parent) == rbe)
RBE_LEFT(parent) = child;
else
RBE_RIGHT(parent) = child;
rbe_if_augment(t, parent);
} else
RBH_ROOT(rbt) = child;
color:
if (color == RB_BLACK)
rbe_remove_color(t, rbt, parent, child);
return (old);
}
void *_rb_remove(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
{
struct rb_entry *rbe = rb_n2e(t, elm);
struct rb_entry *old;
old = rbe_remove(t, rbt, rbe);
return (old == NULL ? NULL : rb_e2n(t, old));
}
void *_rb_insert(const struct rb_type *t, struct rbt_tree *rbt, void *elm)
{
struct rb_entry *rbe = rb_n2e(t, elm);
struct rb_entry *tmp;
struct rb_entry *parent = NULL;
void *node;
int comp = 0;
tmp = RBH_ROOT(rbt);
while (tmp != NULL) {
parent = tmp;
node = rb_e2n(t, tmp);
comp = (*t->t_compare)(elm, node);
if (comp < 0)
tmp = RBE_LEFT(tmp);
else if (comp > 0)
tmp = RBE_RIGHT(tmp);
else
return (node);
}
rbe_set(rbe, parent);
if (parent != NULL) {
if (comp < 0)
RBE_LEFT(parent) = rbe;
else
RBE_RIGHT(parent) = rbe;
rbe_if_augment(t, parent);
} else
RBH_ROOT(rbt) = rbe;
rbe_insert_color(t, rbt, rbe);
return (NULL);
}
/* Finds the node with the same key as elm */
void *_rb_find(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
{
struct rb_entry *tmp = RBH_ROOT(rbt);
void *node;
int comp;
while (tmp != NULL) {
node = rb_e2n(t, tmp);
comp = (*t->t_compare)(key, node);
if (comp < 0)
tmp = RBE_LEFT(tmp);
else if (comp > 0)
tmp = RBE_RIGHT(tmp);
else
return (node);
}
return (NULL);
}
/* Finds the first node greater than or equal to the search key */
void *_rb_nfind(const struct rb_type *t, struct rbt_tree *rbt, const void *key)
{
struct rb_entry *tmp = RBH_ROOT(rbt);
void *node;
void *res = NULL;
int comp;
while (tmp != NULL) {
node = rb_e2n(t, tmp);
comp = (*t->t_compare)(key, node);
if (comp < 0) {
res = node;
tmp = RBE_LEFT(tmp);
} else if (comp > 0)
tmp = RBE_RIGHT(tmp);
else
return (node);
}
return (res);
}
void *_rb_next(const struct rb_type *t, void *elm)
{
struct rb_entry *rbe = rb_n2e(t, elm);
if (RBE_RIGHT(rbe) != NULL) {
rbe = RBE_RIGHT(rbe);
while (RBE_LEFT(rbe) != NULL)
rbe = RBE_LEFT(rbe);
} else {
if (RBE_PARENT(rbe) && (rbe == RBE_LEFT(RBE_PARENT(rbe))))
rbe = RBE_PARENT(rbe);
else {
while (RBE_PARENT(rbe)
&& (rbe == RBE_RIGHT(RBE_PARENT(rbe))))
rbe = RBE_PARENT(rbe);
rbe = RBE_PARENT(rbe);
}
}
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
}
void *_rb_prev(const struct rb_type *t, void *elm)
{
struct rb_entry *rbe = rb_n2e(t, elm);
if (RBE_LEFT(rbe)) {
rbe = RBE_LEFT(rbe);
while (RBE_RIGHT(rbe))
rbe = RBE_RIGHT(rbe);
} else {
if (RBE_PARENT(rbe) && (rbe == RBE_RIGHT(RBE_PARENT(rbe))))
rbe = RBE_PARENT(rbe);
else {
while (RBE_PARENT(rbe)
&& (rbe == RBE_LEFT(RBE_PARENT(rbe))))
rbe = RBE_PARENT(rbe);
rbe = RBE_PARENT(rbe);
}
}
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
}
void *_rb_root(const struct rb_type *t, struct rbt_tree *rbt)
{
struct rb_entry *rbe = RBH_ROOT(rbt);
return (rbe == NULL ? rbe : rb_e2n(t, rbe));
}
void *_rb_min(const struct rb_type *t, struct rbt_tree *rbt)
{
struct rb_entry *rbe = RBH_ROOT(rbt);
struct rb_entry *parent = NULL;
while (rbe != NULL) {
parent = rbe;
rbe = RBE_LEFT(rbe);
}
return (parent == NULL ? NULL : rb_e2n(t, parent));
}
void *_rb_max(const struct rb_type *t, struct rbt_tree *rbt)
{
struct rb_entry *rbe = RBH_ROOT(rbt);
struct rb_entry *parent = NULL;
while (rbe != NULL) {
parent = rbe;
rbe = RBE_RIGHT(rbe);
}
return (parent == NULL ? NULL : rb_e2n(t, parent));
}
void *_rb_left(const struct rb_type *t, void *node)
{
struct rb_entry *rbe = rb_n2e(t, node);
rbe = RBE_LEFT(rbe);
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
}
void *_rb_right(const struct rb_type *t, void *node)
{
struct rb_entry *rbe = rb_n2e(t, node);
rbe = RBE_RIGHT(rbe);
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
}
void *_rb_parent(const struct rb_type *t, void *node)
{
struct rb_entry *rbe = rb_n2e(t, node);
rbe = RBE_PARENT(rbe);
return (rbe == NULL ? NULL : rb_e2n(t, rbe));
}
void _rb_set_left(const struct rb_type *t, void *node, void *left)
{
struct rb_entry *rbe = rb_n2e(t, node);
struct rb_entry *rbl = (left == NULL) ? NULL : rb_n2e(t, left);
RBE_LEFT(rbe) = rbl;
}
void _rb_set_right(const struct rb_type *t, void *node, void *right)
{
struct rb_entry *rbe = rb_n2e(t, node);
struct rb_entry *rbr = (right == NULL) ? NULL : rb_n2e(t, right);
RBE_RIGHT(rbe) = rbr;
}
void _rb_set_parent(const struct rb_type *t, void *node, void *parent)
{
struct rb_entry *rbe = rb_n2e(t, node);
struct rb_entry *rbp = (parent == NULL) ? NULL : rb_n2e(t, parent);
RBE_PARENT(rbe) = rbp;
}
void _rb_poison(const struct rb_type *t, void *node, unsigned long poison)
{
struct rb_entry *rbe = rb_n2e(t, node);
RBE_PARENT(rbe) = RBE_LEFT(rbe) = RBE_RIGHT(rbe) =
(struct rb_entry *)poison;
}
int _rb_check(const struct rb_type *t, void *node, unsigned long poison)
{
struct rb_entry *rbe = rb_n2e(t, node);
return ((unsigned long)RBE_PARENT(rbe) == poison
&& (unsigned long)RBE_LEFT(rbe) == poison
&& (unsigned long)RBE_RIGHT(rbe) == poison);
}

View File

@ -28,8 +28,23 @@
#include "../include/port.h"
#include "../include/system.h"
#include "../include/iccp_csm.h"
#include "../include/iccp_netlink.h"
#include "../include/mlacp_link_handler.h"
#include "../include/scheduler.h"
#include "../include/iccp_netlink.h"
#include "../include/iccp_ifm.h"
static int vlan_node_compare(const struct VLAN_ID *p_vlan_node1, const struct VLAN_ID *p_vlan_node2)
{
if (p_vlan_node1->vid < p_vlan_node2->vid)
return -1;
if (p_vlan_node1->vid > p_vlan_node2->vid)
return 1;
return 0;
}
RB_GENERATE(vlan_rb_tree, VLAN_ID, vlan_entry, vlan_node_compare);
void local_if_init(struct LocalInterface* local_if)
{
@ -46,11 +61,14 @@ void local_if_init(struct LocalInterface* local_if)
local_if->is_peer_link = 0;
local_if->is_arp_accept = 0;
local_if->l3_mode = 0;
local_if->master_ifindex = 0;
local_if->state = PORT_STATE_DOWN;
local_if->prefixlen = 32;
local_if->csm = NULL;
local_if->isolate_to_peer_link = 0;
LIST_INIT(&local_if->vlan_list);
local_if->is_l3_proto_enabled = false;
local_if->vlan_count = 0;
RB_INIT(vlan_rb_tree, &local_if->vlan_tree);
return;
}
@ -64,7 +82,7 @@ void vlan_info_init(struct VLAN_ID* vlan)
return;
}
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type, uint8_t state)
{
struct System* sys = NULL;
struct LocalInterface* local_if = NULL;
@ -77,11 +95,10 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
if (!(sys = system_get_instance()))
return NULL;
if (ifindex < 0)
return NULL;
if (ifindex > 0) {
if ((local_if = local_if_find_by_ifindex(ifindex)))
return local_if;
}
if (!(local_if = (struct LocalInterface*)malloc(sizeof(struct LocalInterface))))
{
@ -92,6 +109,9 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
local_if_init(local_if);
local_if->ifindex = ifindex;
local_if->type = type;
local_if->state = state;
local_if->po_down_time = 0;
if (local_if->type == IF_T_PORT_CHANNEL)
{
@ -107,6 +127,7 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
return NULL;
local_if->po_id = atoi(&ifname[i]);
local_if->po_active = (state == PORT_STATE_UP) ? 1 : 0;
}
if (ifname)
@ -121,7 +142,10 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
break;
case IF_T_VLAN:
/* do nothing currently. */
if(is_unique_ip_configured(local_if->name))
{
local_if->is_l3_proto_enabled = true;
}
break;
case IF_T_VXLAN:
@ -142,6 +166,9 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
LIST_INSERT_HEAD(&(sys->lif_list), local_if, system_next);
//if there is pending vlan membership for this interface move to system lif
move_pending_vlan_mbr_to_lif(sys, local_if);
/*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/
/*When set peer-link, the local-if is probably not created*/
LIST_FOREACH(csm, &(sys->csm_list), next)
@ -150,6 +177,7 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
{
local_if->is_peer_link = 1;
csm->peer_link_if = local_if;
set_peerlink_learn_kernel(csm, 0, 3);
break;
}
/*check the intf is bind with csm*/
@ -217,21 +245,37 @@ struct LocalInterface* local_if_find_by_po_id(int po_id)
return NULL;
}
static void local_if_vlan_remove(struct LocalInterface *lif_vlan)
void local_if_vlan_remove(struct LocalInterface *lif_vlan)
{
struct System *sys = NULL;
struct LocalInterface *lif = NULL;
struct VLAN_ID *vlan = NULL;
int vid = 0;
struct VLAN_ID vlan_key = { 0 };
if (!lif_vlan || lif_vlan->type != IF_T_VLAN)
{
return;
}
sscanf(lif_vlan->name, "Vlan%d", &vid);
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
vlan_key.vid = vid;
if ((sys = system_get_instance()) != NULL)
{
LIST_FOREACH(lif, &(sys->lif_list), system_next)
{
LIST_FOREACH(vlan, &(lif->vlan_list), port_next)
{
if (lif_vlan != vlan->vlan_itf)
if (lif->type == IF_T_VLAN)
continue;
//delink this vlan (lif_vlan) interface from all associated lifs
//in scenario where vlan membership delete comes later when compared
//to vlan interface delete from kernel
vlan = RB_FIND(vlan_rb_tree, &(lif->vlan_tree), &vlan_key);
if (vlan)
{
vlan->vlan_itf = NULL;
}
}
@ -279,6 +323,7 @@ void local_if_destroy(char *ifname)
{
struct LocalInterface* lif = NULL;
struct CSM *csm = NULL;
struct CSM *peer_ifname_csm = NULL;
struct System *sys = NULL;
if (!(sys = system_get_instance()))
@ -297,15 +342,21 @@ void local_if_destroy(char *ifname)
else
local_if_remove(lif);
csm = lif->csm;
if (csm && csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0)
//handle peer_link del case
if ( (peer_ifname_csm = system_get_csm_by_peer_ifname(ifname)) != NULL )
{
/*if the peerlink interface is not created, peer connection can not establish*/
scheduler_session_disconnect_handler(csm);
scheduler_session_disconnect_handler(peer_ifname_csm);
// The function above calls iccp_csm_status_reset, which sets csm->Peer_link_if to NULL,
// accessing the peer_link_if cause crash due to null pointer access.
#if 0
csm->peer_link_if->is_peer_link = 0;
csm->peer_link_if = NULL;
#endif
}
csm = lif->csm;
if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
goto to_mlacp_purge;
else
@ -336,8 +387,11 @@ int local_if_is_l3_mode(struct LocalInterface* local_if)
if (local_if == NULL)
return 0;
if (local_if->ipv4_addr != 0 || memcmp(local_if->ipv6_addr, addr_null, 16) != 0)
if ((local_if->ipv4_addr != 0)
|| (memcmp(local_if->ipv6_addr, addr_null, 16) != 0)
|| (local_if->master_ifindex != 0)) {
ret = 1;
}
return ret;
}
@ -361,6 +415,25 @@ void local_if_change_flag_clear(void)
return;
}
static void local_if_mlacp_purge_del(struct LocalInterface* lif)
{
struct CSM* csm;
struct LocalInterface *lif_purge;
if (lif && lif->csm)
{
LIST_FOREACH(lif_purge, &(MLACP(lif->csm).lif_purge_list), mlacp_purge_next)
{
if (lif_purge == lif)
{
LIST_REMOVE(lif, mlacp_purge_next);
break;
}
}
}
}
void local_if_purge_clear(void)
{
struct System* sys = NULL;
@ -375,8 +448,7 @@ void local_if_purge_clear(void)
lif = LIST_FIRST(&(sys->lif_purge_list));
ICCPD_LOG_DEBUG(__FUNCTION__, "Purge %s", lif->name);
LIST_REMOVE(lif, system_purge_next);
if (lif->mlacp_purge_next.le_next != 0 && lif->mlacp_purge_next.le_prev != 0)
LIST_REMOVE(lif, mlacp_purge_next);
local_if_mlacp_purge_del(lif);
local_if_del_all_vlan(lif);
free(lif);
}
@ -470,17 +542,15 @@ struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name)
void peer_if_del_all_vlan(struct PeerInterface* pif)
{
struct VLAN_ID *pvlan = NULL;
struct VLAN_ID *vlan = NULL;
struct VLAN_ID* vlan_temp = NULL;
while (!LIST_EMPTY(&(pif->vlan_list)))
ICCPD_LOG_NOTICE(__FUNCTION__, "Remove all VLANs from peer intf %s", pif->name);
RB_FOREACH_SAFE(vlan, vlan_rb_tree, &(pif->vlan_tree), vlan_temp)
{
pvlan = LIST_FIRST(&(pif->vlan_list));
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d",
pif->name, pvlan->vid);
LIST_REMOVE(pvlan, port_next);
free(pvlan);
VLAN_RB_REMOVE(vlan_rb_tree, &(pif->vlan_tree), vlan);
free(vlan);
}
return;
}
@ -500,16 +570,15 @@ void peer_if_destroy(struct PeerInterface* pif)
int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid)
{
struct VLAN_ID *vlan = NULL;
struct VLAN_ID vlan_key = { 0 };
char vlan_name[16] = "";
sprintf(vlan_name, "Vlan%d", vid);
/* traverse 1 time */
LIST_FOREACH(vlan, &(local_if->vlan_list), port_next)
{
if (vlan->vid == vid)
break;
}
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
vlan_key.vid = vid;
vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), &vlan_key);
if (!vlan)
{
@ -517,53 +586,67 @@ int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid)
if (!vlan)
return MCLAG_ERROR;
ICCPD_LOG_DEBUG(__FUNCTION__, "Add %s to VLAN %d", local_if->name, vid);
local_if->port_config_sync = 1;
LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next);
}
vlan_info_init(vlan);
vlan->vid = vid;
vlan->vlan_removed = 0;
vlan->vlan_itf = local_if_find_by_name(vlan_name);
update_if_ipmac_on_standby(local_if);
if (vlan->vlan_itf == NULL) {
ICCPD_LOG_DEBUG(__FUNCTION__, "vlan_itf %s not present", vlan_name);
}
local_if->vlan_count +=1;
ICCPD_LOG_DEBUG(__FUNCTION__, "Add %s to VLAN %d vlan count %d", local_if->name, vid, local_if->vlan_count);
local_if->port_config_sync = 1;
RB_INSERT(vlan_rb_tree, &(local_if->vlan_tree), vlan);
}
vlan->vlan_removed = 0;
// update_if_ipmac_on_standby(local_if, 5);
if (vlan->vlan_itf)
{
if (local_if->is_peer_link)
{
update_vlan_if_mac_on_standby(vlan->vlan_itf, 1);
}
}
else
{
ICCPD_LOG_WARN(__FUNCTION__, "skip VLAN MAC update for vlan %d interface %s ", vid, local_if->name);
}
return 0;
}
void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid)
{
struct VLAN_ID *vlan = NULL;
struct VLAN_ID vlan_key = { 0 };
/* traverse 1 time */
LIST_FOREACH(vlan, &(local_if->vlan_list), port_next)
{
if (vlan->vid == vid)
break;
}
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
vlan_key.vid = vid;
vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), &vlan_key);
if (vlan != NULL)
{
LIST_REMOVE(vlan, port_next);
VLAN_RB_REMOVE(vlan_rb_tree, &(local_if->vlan_tree), vlan);
free(vlan);
local_if->port_config_sync = 1;
local_if->vlan_count -=1;
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d, count %d", local_if->name, vid, local_if->vlan_count);
}
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", local_if->name, vid);
return;
}
void local_if_del_all_vlan(struct LocalInterface* lif)
{
struct VLAN_ID* vlan = NULL;
struct VLAN_ID* vlan_temp = NULL;
while (!LIST_EMPTY(&(lif->vlan_list)))
ICCPD_LOG_NOTICE(__FUNCTION__, "Remove all VLANs from %s", lif->name);
RB_FOREACH_SAFE(vlan, vlan_rb_tree, &(lif->vlan_tree), vlan_temp)
{
vlan = LIST_FIRST(&(lif->vlan_list));
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid);
LIST_REMOVE(vlan, port_next);
VLAN_RB_REMOVE(vlan_rb_tree, &(lif->vlan_tree), vlan);
lif->vlan_count -=1;
free(vlan);
}
@ -574,19 +657,15 @@ void local_if_del_all_vlan(struct LocalInterface* lif)
int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id)
{
struct VLAN_ID *peer_vlan = NULL;
struct VLAN_ID vlan_key = { 0 };
char vlan_name[16] = "";
sprintf(vlan_name, "Vlan%d", vlan_id);
/* traverse 1 time */
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next)
{
if (peer_vlan->vid == vlan_id)
{
ICCPD_LOG_DEBUG(__FUNCTION__, "Update VLAN ID %d for peer intf %s", peer_vlan->vid, peer_if->name);
break;
}
}
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
vlan_key.vid = vlan_id;
peer_vlan = RB_FIND(vlan_rb_tree, &(peer_if->vlan_tree), &vlan_key);
if (!peer_vlan)
{
@ -594,14 +673,14 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id)
if (!peer_vlan)
return MCLAG_ERROR;
ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer intf %s to VLAN %d", peer_if->name, vlan_id);
LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next);
}
vlan_info_init(peer_vlan);
peer_vlan->vid = vlan_id;
peer_vlan->vlan_removed = 0;
ICCPD_LOG_DEBUG(__FUNCTION__, "add VLAN ID = %d from peer's %s", vlan_id, peer_if->name);
RB_INSERT(vlan_rb_tree, &(peer_if->vlan_tree), peer_vlan);
}
peer_vlan->vlan_removed = 0;
return 0;
}
@ -610,14 +689,15 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if)
{
struct VLAN_ID *peer_vlan = NULL;
struct VLAN_ID *peer_vlan_next = NULL;
struct VLAN_ID *vlan_temp = NULL;
/* traverse 1 time */
LIST_FOREACH(peer_vlan_next, &(peer_if->vlan_list), port_next)
RB_FOREACH_SAFE(peer_vlan_next, vlan_rb_tree, &(peer_if->vlan_tree), vlan_temp)
{
if (peer_vlan != NULL)
{
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid);
LIST_REMOVE(peer_vlan, port_next);
VLAN_RB_REMOVE(vlan_rb_tree, &(peer_if->vlan_tree), peer_vlan);
free(peer_vlan);
peer_vlan = NULL;
@ -629,7 +709,7 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if)
if (peer_vlan != NULL)
{
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid);
LIST_REMOVE(peer_vlan, port_next);
VLAN_RB_REMOVE(vlan_rb_tree, &(peer_if->vlan_tree), peer_vlan);
free(peer_vlan);
}
@ -660,9 +740,32 @@ int set_sys_arp_accept_flag(char* ifname, int flag)
memset(cmd, 0, 64);
snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname);
if (system(cmd))
ICCPD_LOG_WARN(__func__, "Failed to execute cmd = %s", flag, cmd);
ICCPD_LOG_WARN(__func__, "Failed to execute cmd = %s", cmd);
}
fclose(file_ptr);
return result;
}
int local_if_l3_proto_enabled(const char* ifname)
{
struct System* sys = NULL;
struct LocalInterface* local_if = NULL;
if (!ifname)
return 0;
if (!(sys = system_get_instance()))
return 0;
LIST_FOREACH(local_if, &(sys->lif_list), system_next)
{
if (strcmp(local_if->name, ifname) == 0)
{
if (local_if->is_l3_proto_enabled)
return 1;
}
}
return 0;
}

View File

@ -48,6 +48,14 @@
*
******************************************************/
//this needs to be fine tuned
#define PEER_SOCK_SND_BUF_LEN (6 * 1024 * 1024)
#define PEER_SOCK_RCV_BUF_LEN (6 * 1024 * 1024)
#define RECV_RETRY_INTERVAL_USEC 100000
#define RECV_RETRY_MAX 10
extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size);
static int session_conn_thread_lock(pthread_mutex_t *conn_mutex)
{
return 1; /*pthread_mutex_lock(conn_mutex);*/
@ -71,10 +79,10 @@ static void heartbeat_check(struct CSM *csm)
return;
}
if ( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC)
if ( (time(NULL) - csm->heartbeat_update_time) > csm->session_timeout)
{
/* hearbeat timeout*/
ICCPD_LOG_WARN(__FUNCTION__, "iccpd connection timeout (heartbeat)");
ICCPD_LOG_WARN("ICCP_FSM", "iccpd connection timeout (heartbeat)");
scheduler_session_disconnect_handler(csm);
}
@ -106,15 +114,13 @@ static int scheduler_transit_fsm()
iccp_csm_transit(csm);
app_csm_transit(csm);
mlacp_fsm_transit(csm);
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE && (time(NULL) - sys->csm_trans_time) >= 60)
{
iccp_get_fdb_change_from_syncd();
sys->csm_trans_time = time(NULL);
}
}
local_if_change_flag_clear();
//lif->changed flag is marked for state change for lif, for active node when
//it is in STAGE2 where it receiving cfg sync from peer if there is any po
//state change that change is not sent and this clear clears the marking and
//thus remote state is not updated; so commenting this out
//local_if_change_flag_clear();
local_if_purge_clear();
return 1;
@ -131,6 +137,9 @@ int scheduler_csm_read_callback(struct CSM* csm)
size_t data_len = 0;
size_t pos = 0;
int recv_len = 0, len = 0, retval;
int num_retry = 0;
int total_retry_time = 0;
int total_data_len = 0;
if (csm->sock_fd <= 0)
return MCLAG_ERROR;
@ -138,6 +147,7 @@ int scheduler_csm_read_callback(struct CSM* csm)
memset(peer_msg, 0, CSM_BUFFER_SIZE);
recv_len = 0;
errno = 0;
while (recv_len != sizeof(LDPHdr))
{
@ -145,38 +155,92 @@ int scheduler_csm_read_callback(struct CSM* csm)
if (len == -1)
{
perror("recv(). Error");
ICCPD_LOG_WARN("ICCP_FSM", "Peer disconnect for header read error[%s] len = -1 till now received len = %d ", strerror(errno), recv_len);
SYSTEM_INCR_HDR_READ_SOCK_ERR_COUNTER(system_get_instance());
goto recv_err;
}
else if (len == 0)
{
ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for receive error");
ICCPD_LOG_WARN("ICCP_FSM", "Peer disconnect for header read error[%s] len = 0, till now received len = %d ",strerror(errno), recv_len);
SYSTEM_INCR_HDR_READ_SOCK_ZERO_LEN_COUNTER(system_get_instance());
goto recv_err;
}
recv_len += len;
/*usleep(100);*/
}
if (ntohs(ldp_hdr->msg_len) >= MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS)
{
data_len = ntohs(ldp_hdr->msg_len) - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS;
}
else
{
ICCPD_LOG_ERR("ICCP_FSM", "Peer disconnect for invalid data error; length[%d] msg_type[0x%x] ", ntohs(ldp_hdr->msg_len), ntohs(ldp_hdr->msg_type));
SYSTEM_INCR_INVALID_PEER_MSG_COUNTER(system_get_instance());
goto recv_err;
}
total_data_len = data_len;
pos = 0;
while (data_len > 0)
{
recv_len = recv(csm->sock_fd, &data[pos], data_len, 0);
/* When consecutive CCP session flaps happen, recv() call got stuck.
* Change recv() to non-blocking with retry mechanism. If max
* retry reaches, attempt one more retry after waiting for one KA
* interval before bringing down the session.
*/
recv_len = recv(csm->sock_fd, &data[pos], data_len, MSG_DONTWAIT);
if (recv_len == -1)
{
perror("continue recv(). Error");
if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
{
ICCPD_LOG_NOTICE(
"ICCP_FSM", "Non-blocking recv total/pending len %d/%d, errno %d, num_retry %d",
total_data_len, data_len, errno, num_retry);
++num_retry;
if (num_retry > RECV_RETRY_MAX)
{
ICCPD_LOG_ERR(
"ICCP_FSM", "Non-blocking recv() retry failed, total/pending len %d/%d",
total_data_len, data_len);
SYSTEM_INCR_RX_RETRY_FAIL_COUNTER(system_get_instance());
goto recv_err;
}
else
{
if (num_retry == RECV_RETRY_MAX)
usleep((csm->session_timeout * 1000000) - total_retry_time);
else
{
total_retry_time += (num_retry * RECV_RETRY_INTERVAL_USEC);
usleep(num_retry * RECV_RETRY_INTERVAL_USEC);
}
recv_len = 0;
}
}
else
{
perror("continue recv() Error");
ICCPD_LOG_WARN("ICCP_FSM", "Peer data read error; recv_len:%d data_len:%d, errno %d",
recv_len, data_len, errno);
SYSTEM_INCR_TLV_READ_SOCK_ERR_COUNTER(system_get_instance());
goto recv_err;
}
}
else if (recv_len == 0)
{
ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for read error");
ICCPD_LOG_WARN("ICCP_FSM", "Peer disconnect for data read error; recv_len:%d data_len:%d ", recv_len, data_len);
SYSTEM_INCR_TLV_READ_SOCK_ZERO_LEN_COUNTER(system_get_instance());
goto recv_err;
}
data_len -= recv_len;
pos += recv_len;
/*usleep(100);*/
}
if (num_retry > 0)
{
SYSTEM_SET_RETRY_COUNTER(system_get_instance(), num_retry);
}
retval = iccp_csm_init_msg(&msg, peer_msg, ntohs(ldp_hdr->msg_len) + MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS);
if (retval == 0)
{
@ -224,21 +288,21 @@ int scheduler_server_accept()
if (!csm)
{
/* can't find csm with peer ip*/
ICCPD_LOG_INFO(__FUNCTION__, "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
ICCPD_LOG_NOTICE("ICCP_FSM", "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
goto reject_client;
}
if (csm->sock_fd > 0)
{
/* peer already connected*/
ICCPD_LOG_INFO(__FUNCTION__, "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
ICCPD_LOG_NOTICE("ICCP_FSM", "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
goto reject_client;
}
if ((ret = scheduler_check_csm_config(csm)) < 0)
{
/* csm config error*/
ICCPD_LOG_INFO(__FUNCTION__, "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
ICCPD_LOG_NOTICE("ICCP_FSM", "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
goto reject_client;
}
}
@ -257,6 +321,8 @@ int scheduler_server_accept()
struct epoll_event event;
int err;
int send_buf_len = PEER_SOCK_SND_BUF_LEN;
int recv_buf_len = PEER_SOCK_RCV_BUF_LEN;
event.data.fd = new_fd;
event.events = EPOLLIN;
err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event);
@ -267,6 +333,14 @@ int scheduler_server_accept()
}
csm->sock_fd = new_fd;
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_SNDBUF, &send_buf_len, sizeof(send_buf_len)) == -1)
{
ICCPD_LOG_ERR(__FUNCTION__, "Set socket send buf option failed. Error");
}
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)) == -1)
{
ICCPD_LOG_ERR(__FUNCTION__, "Set socket recv buf option failed. Error");
}
csm->current_state = ICCP_NONEXISTENT;
FD_SET(new_fd, &(sys->readfd));
sys->readfd_count++;
@ -293,6 +367,8 @@ void iccp_get_start_type(struct System* sys)
if (strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm"))
sys->warmboot_start = WARM_REBOOT;
ICCPD_LOG_DEBUG("ICCP_FSM", "Start ICCP: warm reboot %s",
(sys->warmboot_start == WARM_REBOOT)? "yes" : "no");
return;
}
@ -309,6 +385,8 @@ void scheduler_init()
iccp_sys_local_if_list_get_init();
iccp_sys_local_if_list_get_addr();
/*Interfaces must be created before this func called*/
//no need to create iccpd config from startup file, it will be done through
//cli
iccp_config_from_file(sys->config_file_path);
/*Get kernel ARP info */
@ -331,7 +409,6 @@ void scheduler_init()
return;
}
extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size);
void mlacp_sync_send_warmboot_flag()
{
struct System* sys = NULL;
@ -350,7 +427,7 @@ void mlacp_sync_send_warmboot_flag()
iccp_csm_send(csm, g_csm_buf, msg_len);
}
}
ICCPD_LOG_DEBUG("ICCP_FSM", "Send warmboot flag to peer. Start warmboot");
return;
}
@ -542,12 +619,23 @@ void session_client_conn_handler(struct CSM *csm)
/* Conn OK*/
struct epoll_event event;
int err;
int send_buf_len = PEER_SOCK_SND_BUF_LEN;
int recv_buf_len = PEER_SOCK_RCV_BUF_LEN;
event.data.fd = connFd;
event.events = EPOLLIN;
err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event);
if (err)
goto conn_fail;
csm->sock_fd = connFd;
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_SNDBUF, &send_buf_len, sizeof(send_buf_len)) == -1)
{
ICCPD_LOG_ERR(__FUNCTION__, "Set socket send buf option failed. Error");
}
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)) == -1)
{
ICCPD_LOG_ERR(__FUNCTION__, "Set socket recv buf option failed. Error");
}
FD_SET(connFd, &(sys->readfd));
sys->readfd_count++;
ICCPD_LOG_INFO(__FUNCTION__, "Connect to server %s sucess .", csm->peer_ip);
@ -707,6 +795,7 @@ int scheduler_check_csm_config(struct CSM* csm)
{
lif->is_peer_link = 1;
csm->peer_link_if = lif;
set_peerlink_learn_kernel(csm, 0, 2);
}
}
@ -742,32 +831,66 @@ int scheduler_unregister_sock_read_event_callback(struct CSM* csm)
void scheduler_session_disconnect_handler(struct CSM* csm)
{
struct System* sys = NULL;
struct If_info * cif = NULL;
if ((sys = system_get_instance()) == NULL )
return;
struct epoll_event event;
if (csm == NULL)
return;
ICCPD_LOG_NOTICE("ICCP_FSM", "scheduler session disconnect handler");
session_conn_thread_lock(&csm->conn_mutex);
scheduler_unregister_sock_read_event_callback(csm);
if (csm->sock_fd > 0)
{
event.data.fd = csm->sock_fd;
event.events = EPOLLIN;
epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event);
close(csm->sock_fd);
csm->sock_fd = -1;
scheduler_csm_socket_cleanup(csm, 1);
}
mlacp_peer_disconn_handler(csm);
MLACP(csm).current_state = MLACP_STATE_INIT;
iccp_csm_status_reset(csm, 0);
time(&csm->connTimePrev);
session_conn_thread_unlock(&csm->conn_mutex);
return;
}
void scheduler_csm_socket_cleanup(struct CSM* csm, int location)
{
struct System* sys;
struct epoll_event event;
sys = system_get_instance();
if (sys == NULL)
return;
if (csm == NULL)
return;
if (csm->sock_fd <= 0)
return
event.data.fd = csm->sock_fd;
event.events = EPOLLIN;
if (epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event) != 0)
{
ICCPD_LOG_ERR("ICCP_FSM", "CSM socket %d epoll del error %d, location %d",
csm->sock_fd, errno, location);
}
if (close(csm->sock_fd) != 0)
{
ICCPD_LOG_ERR("ICCP_FSM", "CSM socket %d close error %d, location %d",
csm->sock_fd, errno, location);
SYSTEM_INCR_SOCKET_CLOSE_ERR_COUNTER(system_get_instance());
}
else
{
ICCPD_LOG_NOTICE("ICCP_FSM", "CSM socket %d close, location %d",
csm->sock_fd, location);
}
csm->sock_fd = -1;
}

View File

@ -22,11 +22,17 @@
*/
#include <stdio.h>
#include <netlink/msg.h>
#include "../include/iccp_csm.h"
#include "../include/logger.h"
#include "../include/iccp_netlink.h"
#include "../include/scheduler.h"
#include "../include/mlacp_link_handler.h"
#include "../include/iccp_ifm.h"
#define ETHER_ADDR_LEN 6
char mac_print_str[ETHER_ADDR_STR_LEN];
/* Singleton */
struct System* system_get_instance()
@ -53,6 +59,7 @@ void system_init(struct System* sys)
if (sys == NULL )
return;
memset(sys, 0, sizeof(struct System));
sys->server_fd = -1;
sys->sync_fd = -1;
sys->sync_ctrl_fd = -1;
@ -65,6 +72,8 @@ void system_init(struct System* sys)
LIST_INIT(&(sys->csm_list));
LIST_INIT(&(sys->lif_list));
LIST_INIT(&(sys->lif_purge_list));
LIST_INIT(&(sys->unq_ip_if_list));
LIST_INIT(&(sys->pending_vlan_mbr_if_list));
sys->log_file_path = strdup("/var/log/iccpd.log");
sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty");
@ -88,15 +97,21 @@ void system_finalize()
struct System* sys = NULL;
struct CSM* csm = NULL;
struct LocalInterface* local_if = NULL;
struct Unq_ip_If_info* unq_ip_if = NULL;
if ((sys = system_get_instance()) == NULL )
return;
ICCPD_LOG_INFO(__FUNCTION__, "System resource pool is destructing.");
ICCPD_LOG_NOTICE(__FUNCTION__,
"System resource pool is destructing. Warmboot exit (%d)",
sys->warmboot_exit);
while (!LIST_EMPTY(&(sys->csm_list)))
{
csm = LIST_FIRST(&(sys->csm_list));
/* Remove ICCP info from STATE_DB if it is not warm reboot */
if (sys->warmboot_exit != WARM_REBOOT)
mlacp_link_del_iccp_info(csm->mlag_id);
iccp_csm_finalize(csm);
}
@ -115,6 +130,16 @@ void system_finalize()
local_if_finalize(local_if);
}
//remove all pending vlan membership entries
del_all_pending_vlan_mbr_ifs(sys);
while (!LIST_EMPTY(&(sys->unq_ip_if_list)))
{
unq_ip_if = LIST_FIRST(&(sys->unq_ip_if_list));
LIST_REMOVE(unq_ip_if, if_next);
free(unq_ip_if);
}
iccp_system_dinit_netlink_socket();
if (sys->log_file_path != NULL )
@ -185,6 +210,34 @@ struct CSM* system_get_csm_by_peer_ip(const char* peer_ip)
return NULL;
}
//function to get CSM by peer interface name
struct CSM* system_get_csm_by_peer_ifname(char *ifname)
{
struct CSM *csm = NULL;
struct System* sys = NULL;
if (!ifname)
{
return NULL;
}
if ((sys = system_get_instance()) == NULL)
{
return NULL;
}
/* traverse all CSM and find matching csm with peer ifname */
LIST_FOREACH(csm, &(sys->csm_list), next)
{
//return matching csm
if (strcmp(ifname, csm->peer_itf_name) == 0)
{
return csm;
}
}
return NULL;
}
struct CSM* system_get_csm_by_mlacp_id(int id)
{
struct System* sys = NULL;
@ -201,3 +254,146 @@ struct CSM* system_get_csm_by_mlacp_id(int id)
return NULL;
}
struct CSM* system_get_first_csm()
{
struct System* sys = NULL;
struct CSM* csm = NULL;
if ((sys = system_get_instance()) == NULL )
return NULL;
LIST_FOREACH(csm, &(sys->csm_list), next)
{
return csm;
}
return NULL;
}
SYNCD_TX_DBG_CNTR_MSG_e system_syncdtx_to_dbg_msg_type(uint32_t msg_type)
{
switch(msg_type)
{
case MCLAG_MSG_TYPE_PORT_ISOLATE:
return SYNCD_TX_DBG_CNTR_MSG_PORT_ISOLATE;
case MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE:
return SYNCD_TX_DBG_CNTR_MSG_PORT_MAC_LEARN_MODE;
case MCLAG_MSG_TYPE_FLUSH_FDB:
return SYNCD_TX_DBG_CNTR_MSG_FLUSH_FDB;
case MCLAG_MSG_TYPE_SET_MAC:
return SYNCD_TX_DBG_CNTR_MSG_SET_IF_MAC;
case MCLAG_MSG_TYPE_SET_FDB:
return SYNCD_TX_DBG_CNTR_MSG_SET_FDB;
case MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_ENABLE:
return SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_ENABLE;
case MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE:
return SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_DISABLE;
case MCLAG_MSG_TYPE_SET_ICCP_STATE:
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_STATE;
case MCLAG_MSG_TYPE_SET_ICCP_ROLE:
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_ROLE;
case MCLAG_MSG_TYPE_SET_ICCP_SYSTEM_ID:
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_SYSTEM_ID;
case MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE:
return SYNCD_TX_DBG_CNTR_MSG_SET_REMOTE_IF_STATE;
case MCLAG_MSG_TYPE_DEL_ICCP_INFO:
return SYNCD_TX_DBG_CNTR_MSG_DEL_ICCP_INFO;
case MCLAG_MSG_TYPE_DEL_REMOTE_IF_INFO:
return SYNCD_TX_DBG_CNTR_MSG_DEL_REMOTE_IF_INFO;
case MCLAG_MSG_TYPE_SET_PEER_LINK_ISOLATION:
return SYNCD_TX_DBG_CNTR_MSG_PEER_LINK_ISOLATION;
case MCLAG_MSG_TYPE_SET_ICCP_PEER_SYSTEM_ID:
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_PEER_SYSTEM_ID;
default:
return SYNCD_TX_DBG_CNTR_MSG_MAX;
}
}
SYNCD_RX_DBG_CNTR_MSG_e system_syncdrx_to_dbg_msg_type(uint32_t msg_type)
{
switch(msg_type)
{
case MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION:
return SYNCD_RX_DBG_CNTR_MSG_MAC;
case MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN:
return SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_DOMAIN;
case MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE:
return SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_IFACE;
case MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP:
return SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_UNIQUE_IP;
case MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES:
return SYNCD_RX_DBG_CNTR_MSG_VLAN_MBR_UPDATES;
default:
return SYNCD_RX_DBG_CNTR_MSG_MAX;
}
}
char *mac_addr_to_str(uint8_t mac_addr[ETHER_ADDR_LEN])
{
memset(mac_print_str, 0, sizeof(mac_print_str));
snprintf(mac_print_str, sizeof(mac_print_str), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
return mac_print_str;
}
void system_update_netlink_counters(
uint16_t netlink_msg_type,
struct nlmsghdr *nlh)
{
struct System *sys;
struct ndmsg *ndm = NLMSG_DATA(nlh);
sys = system_get_instance();
if (!sys)
return;
switch (netlink_msg_type)
{
case RTM_NEWLINK:
++sys->dbg_counters.newlink_count;
break;
case RTM_DELLINK:
++sys->dbg_counters.dellink_count;
break;
case RTM_NEWNEIGH:
++sys->dbg_counters.newnbr_count;
if (ndm->ndm_family == AF_BRIDGE)
++sys->dbg_counters.newmac_count;
break;
case RTM_DELNEIGH:
++sys->dbg_counters.delnbr_count;
if (ndm->ndm_family == AF_BRIDGE)
++sys->dbg_counters.delmac_count;
break;
case RTM_NEWADDR:
++sys->dbg_counters.newaddr_count;
break;
case RTM_DELADDR:
++sys->dbg_counters.deladdr_count;
break;
default:
++sys->dbg_counters.unknown_type_count;
if (sys->dbg_counters.unknown_type_count < 5)
{
ICCPD_LOG_NOTICE(__FUNCTION__, "NETLINK_COUNTER: Unknown type %d", netlink_msg_type);
}
break;
}
}