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

@ -50,18 +50,21 @@ typedef struct cli_param_queue
#define MCLAG_INTF_STR "mclag_interface" #define MCLAG_INTF_STR "mclag_interface"
#define SYSTEM_MAC_STR "system_mac" #define SYSTEM_MAC_STR "system_mac"
int set_mc_lag_id(struct CSM* csm, uint16_t domain); int set_mc_lag_id(struct CSM *csm, uint16_t domain);
int set_peer_link(int mid, const char* ifname); int set_peer_link(int mid, const char *ifname);
int set_local_address(int mid, const char* addr); int set_local_address(int mid, const char *addr);
int set_peer_address(int mid, const char* addr); int set_peer_address(int mid, const char *addr);
int unset_mc_lag_id(struct CSM* csm, uint16_t domain); int unset_mc_lag_id(struct CSM *csm, uint16_t domain);
int unset_peer_link(int mid); int unset_peer_link(int mid);
int unset_local_address(int mid); int unset_local_address(int mid);
int unset_peer_address(int mid); int unset_peer_address(int mid);
int iccp_cli_attach_mclag_domain_to_port_channel(int domain, const char* ifname); int iccp_cli_attach_mclag_domain_to_port_channel(int domain, const char *ifname);
int iccp_cli_detach_mclag_domain_to_port_channel(const char* ifname); int iccp_cli_detach_mclag_domain_to_port_channel(const char *ifname);
int set_local_system_id(const char* mac); int set_local_system_id(const char *mac);
int unset_local_system_id( ); 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 #endif

View File

@ -26,4 +26,7 @@
int iccp_config_from_file(char *config_default_dir); 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_ */ #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_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_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_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 #endif

View File

@ -113,10 +113,15 @@ struct CSM
time_t peer_warm_reboot_time; time_t peer_warm_reboot_time;
time_t warm_reboot_disconn_time; time_t warm_reboot_disconn_time;
char peer_itf_name[IFNAMSIZ]; char peer_itf_name[IFNAMSIZ];
time_t peer_link_learning_retry_time;
char peer_ip[INET_ADDRSTRLEN]; char peer_ip[INET_ADDRSTRLEN];
char sender_ip[INET_ADDRSTRLEN]; char sender_ip[INET_ADDRSTRLEN];
void* sock_read_event_ptr; void* sock_read_event_ptr;
int keepalive_time;
int session_timeout;
int peer_link_learning_enable;
/* Msg queue */ /* Msg queue */
TAILQ_HEAD(msg_list, Msg) msg_list; 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*); 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 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_ */ #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_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 #endif // LACP_IFM_H

View File

@ -26,9 +26,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <unistd.h> #include <unistd.h>
#include <netlink/netlink.h> #include <netlink/netlink.h>
#include <linux/types.h> #include <linux/types.h>
#include "../include/system.h" #include "../include/system.h"
#include "../include/port.h" #include "../include/port.h"
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
@ -37,6 +35,7 @@
#define NDISC_NEIGHBOUR_ADVERTISEMENT 136 #define NDISC_NEIGHBOUR_ADVERTISEMENT 136
#define ND_OPT_TARGET_LL_ADDR 2 #define ND_OPT_TARGET_LL_ADDR 2
#define NEXTHDR_ICMP 58 #define NEXTHDR_ICMP 58
#define ICCP_NLE_SEQ_MISMATCH -16
struct nd_msg struct nd_msg
{ {
@ -51,17 +50,20 @@ struct in6_pktinfo
unsigned int ipi6_ifindex; /* send/recv interface index */ unsigned int ipi6_ifindex; /* send/recv interface index */
}; };
int iccp_get_port_member_list(struct LocalInterface* lif); int iccp_get_port_member_list(struct LocalInterface *lif);
void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg); void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg);
void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg); void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg);
int iccp_system_init_netlink_socket(); int iccp_system_init_netlink_socket();
void iccp_system_dinit_netlink_socket(); void iccp_system_dinit_netlink_socket();
int iccp_init_netlink_event_fd(struct System *sys); int iccp_init_netlink_event_fd(struct System *sys);
int iccp_handle_events(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_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); 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 #endif

View File

@ -26,9 +26,12 @@
#define _MLACP_FSM_H #define _MLACP_FSM_H
#include "../include/port.h" #include "../include/port.h"
#include "../include/mlacp_tlv.h"
#define MLCAP_SYNC_PHY_DEV_SEC 1 /*every 1 sec*/ #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) #define MLACP(csm_ptr) (csm_ptr->app_csm.mlacp)
struct CSM; struct CSM;
@ -47,7 +50,7 @@ typedef enum MLACP_APP_STATE MLACP_APP_STATE_E;
/* for sender only*/ /* for sender only*/
enum MLACP_SYNC_STATE enum MLACP_SYNC_STATE
{ {
MLACP_SYNC_SYSCONF=0, MLACP_SYNC_SYSCONF = 0,
MLACP_SYNC_AGGCONF, MLACP_SYNC_AGGCONF,
MLACP_SYNC_AGGSTATE, MLACP_SYNC_AGGSTATE,
MLACP_SYNC_AGGINFO, MLACP_SYNC_AGGINFO,
@ -66,6 +69,85 @@ struct Remote_System
uint32_t node_id; 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 struct mLACP
{ {
int id; int id;
@ -88,12 +170,16 @@ struct mLACP
TAILQ_HEAD(arp_info_list, Msg) arp_list; TAILQ_HEAD(arp_info_list, Msg) arp_list;
TAILQ_HEAD(ndisc_msg_list, Msg) ndisc_msg_list; TAILQ_HEAD(ndisc_msg_list, Msg) ndisc_msg_list;
TAILQ_HEAD(ndisc_info_list, Msg) ndisc_list; TAILQ_HEAD(ndisc_info_list, Msg) ndisc_list;
TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list; TAILQ_HEAD(mac_msg_list, MACMsg) mac_msg_list;
TAILQ_HEAD(mac_info_list, Msg) mac_list;
struct mac_rb_tree mac_rb;
LIST_HEAD(lif_list, LocalInterface) lif_list; LIST_HEAD(lif_list, LocalInterface) lif_list;
LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list; LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list;
LIST_HEAD(pif_list, PeerInterface) pif_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); 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_fsm_transit(struct CSM* csm);
void mlacp_enqueue_msg(struct CSM*, struct Msg*); void mlacp_enqueue_msg(struct CSM*, struct Msg*);
struct Msg* mlacp_dequeue_msg(struct CSM*); struct Msg* mlacp_dequeue_msg(struct CSM*);
char* mlacp_state(struct CSM* csm);
/* from app_csm*/ /* from app_csm*/
extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if); extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if);
extern int mlacp_unbind_local_if(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 */ #endif /* _MLACP_HANDLER_H */

View File

@ -23,9 +23,16 @@
#ifndef __MLACP_LINK_HANDLER__ #ifndef __MLACP_LINK_HANDLER__
#define __MLACP_LINK_HANDLER__ #define __MLACP_LINK_HANDLER__
#include <stdbool.h>
#include "../include/iccp_csm.h" #include "../include/iccp_csm.h"
#include "../include/mlacp_tlv.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 * 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 peerlink_port_isolate_cleanup(struct CSM* csm);
void update_peerlink_isolate_from_all_csm_lif(struct CSM* csm); void update_peerlink_isolate_from_all_csm_lif(struct CSM* csm);
void del_mac_from_chip(struct MACMsg *mac_msg); ssize_t iccp_send_to_mclagsyncd(uint8_t msg_type, char *send_buff, uint16_t send_len);
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 del_mac_from_chip(struct MACMsg* mac_msg);
void iccp_get_fdb_change_from_syncd(void); 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, uint8_t update_peer);
extern int mclagd_ctl_sock_create(); extern int mclagd_ctl_sock_create();
extern int mclagd_ctl_sock_accept(int fd); extern int mclagd_ctl_sock_accept(int fd);
extern int mclagd_ctl_interactive_process(int client_fd); extern int mclagd_ctl_interactive_process(int client_fd);
extern int parseMacString(const char *str_mac, uint8_t *bin_mac); extern int parseMacString(const char *str_mac, uint8_t *bin_mac);
char *show_ip_str(uint32_t ipv4_addr); char *show_ip_str(uint32_t ipv4_addr);
char *show_ipv6_str(char *ipv6_addr); char *show_ipv6_str(char *ipv6_addr);
void syncd_info_close(); void syncd_info_close();
int iccp_connect_syncd(); 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 #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_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_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_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_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 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_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_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_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_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 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 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 #endif

View File

@ -36,13 +36,14 @@ int mlacp_fsm_update_system_conf(struct CSM* csm, mLACPSysConfigTLV* tlv);
int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv); int mlacp_fsm_update_Aggport_state(struct CSM* csm, mLACPAggPortStateTLV* tlv);
int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv); int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv);
int mlacp_fsm_update_ndisc_info(struct CSM *csm, struct mLACPNDISCInfoTLV* tlv); 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_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv);
int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* 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_arp(struct CSM* csm, struct Msg* msg);
void mlacp_enqueue_ndisc(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); int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf);
int mlacp_fsm_update_port_channel_info(struct CSM* csm, struct mLACPPortChannelInfoTLV* tlv); int mlacp_fsm_update_port_channel_info(struct CSM* csm, struct mLACPPortChannelInfoTLV* tlv);
int mlacp_fsm_update_peerlink_info(struct CSM* csm, struct mLACPPeerLinkInfoTLV* tlv); int mlacp_fsm_update_peerlink_info(struct CSM* csm, struct mLACPPeerLinkInfoTLV* tlv);

View File

@ -28,6 +28,9 @@
#include "../include/msg_format.h" #include "../include/msg_format.h"
#include "../include/port.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_MSB_MASK 0x80
#define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70 #define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70
@ -350,7 +353,8 @@ struct mLACPVLANInfoTLV
struct mLACPMACData struct mLACPMACData
{ {
uint8_t type;/*add or del*/ 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; uint16_t vid;
/*Current if name that set in chip*/ /*Current if name that set in chip*/
char ifname[MAX_L_PORT_NAME]; char ifname[MAX_L_PORT_NAME];
@ -366,17 +370,24 @@ struct mLACPMACInfoTLV
struct mLACPMACData MacEntry[0]; struct mLACPMACData MacEntry[0];
} __attribute__ ((packed)); } __attribute__ ((packed));
#define NEIGH_LOCAL 1
#define NEIGH_REMOTE 2
struct ARPMsg struct ARPMsg
{ {
uint8_t op_type; uint8_t op_type;
uint8_t flag;
uint8_t learn_flag; /*Loacl or Remote*/
char ifname[MAX_L_PORT_NAME]; char ifname[MAX_L_PORT_NAME];
uint32_t ipv4_addr; uint32_t ipv4_addr; // net order
uint8_t mac_addr[ETHER_ADDR_LEN]; uint8_t mac_addr[ETHER_ADDR_LEN];
}; };
struct NDISCMsg struct NDISCMsg
{ {
uint8_t op_type; uint8_t op_type;
uint8_t flag;
uint8_t learn_flag; /*Loacl or Remote*/
char ifname[MAX_L_PORT_NAME]; char ifname[MAX_L_PORT_NAME];
uint32_t ipv6_addr[4]; uint32_t ipv6_addr[4];
uint8_t mac_addr[ETHER_ADDR_LEN]; uint8_t mac_addr[ETHER_ADDR_LEN];
@ -432,11 +443,50 @@ struct mLACPWarmbootTLV
uint8_t warmboot; uint8_t warmboot;
} __attribute__ ((packed)); } __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 enum NEIGH_OP_TYPE
{ {
NEIGH_SYNC_LIF, NEIGH_SYNC_LIF = 0,
NEIGH_SYNC_ADD, NEIGH_SYNC_ADD = 1,
NEIGH_SYNC_DEL, 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 enum MAC_AGE_TYPE
@ -456,20 +506,30 @@ enum MAC_TYPE
{ {
MAC_TYPE_STATIC = 1, MAC_TYPE_STATIC = 1,
MAC_TYPE_DYNAMIC = 2, MAC_TYPE_DYNAMIC = 2,
MAC_TYPE_DYNAMIC_LOCAL = 3, /* Used while sending MAC to Syncd to program with aging enabled. */
}; };
struct MACMsg 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 op_type; /*add or del*/
uint8_t fdb_type; /*static or dynamic*/ uint8_t fdb_type; /*static or dynamic*/
char mac_str[ETHER_ADDR_STR_LEN];
uint16_t vid;
/*Current if name that set in chip*/ /*Current if name that set in chip*/
char ifname[MAX_L_PORT_NAME]; char ifname[MAX_L_PORT_NAME];
/*if we set the mac to peer-link, origin_ifname store the /*if we set the mac to peer-link, origin_ifname store the
original if name that learned from chip*/ original if name that learned from chip*/
char origin_ifname[MAX_L_PORT_NAME]; char origin_ifname[MAX_L_PORT_NAME];
uint8_t age_flag;/*local or peer is age?*/ 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_ */ #endif /* MLACP_TLV_H_ */

View File

@ -29,6 +29,11 @@
#define MAX_MSG_LOG_SIZE 128 #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 * RFC 5561
* 4. Capability Message * 4. Capability Message
@ -99,7 +104,8 @@
#define TLV_T_MLACP_MAC_INFO 0x1038 #define TLV_T_MLACP_MAC_INFO 0x1038
#define TLV_T_MLACP_WARMBOOT_FLAG 0x1039 #define TLV_T_MLACP_WARMBOOT_FLAG 0x1039
#define TLV_T_MLACP_NDISC_INFO 0x103A #define TLV_T_MLACP_NDISC_INFO 0x103A
#define TLV_T_MLACP_LIST_END 0x104a // list end #define TLV_T_MLACP_IF_UP_ACK 0x103B
#define TLV_T_MLACP_LIST_END 0x104a //list end
/* Debug */ /* Debug */
static char* get_tlv_type_string(int type) static char* get_tlv_type_string(int type)
@ -178,6 +184,9 @@ static char* get_tlv_type_string(int type)
case TLV_T_MLACP_STP_INFO: case TLV_T_MLACP_STP_INFO:
return "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"; return "UNKNOWN";
@ -427,7 +436,11 @@ struct AppDisconnectCauseTLV
typedef enum mclag_syncd_msg_type_e_ typedef enum mclag_syncd_msg_type_e_
{ {
MCLAG_SYNCD_MSG_TYPE_NONE = 0, 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; }mclag_syncd_msg_type_e;
typedef enum mclag_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_FLUSH_FDB = 3,
MCLAG_MSG_TYPE_SET_MAC = 4, MCLAG_MSG_TYPE_SET_MAC = 4,
MCLAG_MSG_TYPE_SET_FDB = 5, 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; }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_ENABLE = 3,
MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4,
MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, 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; } 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 struct IccpSyncdHDr
{ {
@ -475,13 +521,39 @@ typedef struct mclag_sub_option_hdr_t_
struct mclag_fdb_info struct mclag_fdb_info
{ {
char mac[ETHER_ADDR_STR_LEN]; uint8_t mac[ETHER_ADDR_LEN];
unsigned int vid; unsigned int vid;
char port_name[MAX_L_PORT_NAME]; char port_name[MAX_L_PORT_NAME];
short type; /*dynamic or static*/ short type; /*dynamic or static*/
short op_type; /*add or del*/ 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 */ /* For storing message log: For Notification TLV */
struct MsgTypeSet 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 MsgLog
{ {
struct MsgTypeSet msg[MAX_MSG_LOG_SIZE]; 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_ #define PORT_H_
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <time.h> #include <time.h>
#include <sys/queue.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_LEN 6
#define ETHER_ADDR_STR_LEN 18 #define ETHER_ADDR_STR_LEN 18
/* /*
@ -50,6 +58,7 @@
#define IF_T_VLAN 2 #define IF_T_VLAN 2
#define IF_T_VXLAN 3 #define IF_T_VXLAN 3
#define IF_T_BRIDGE 4 #define IF_T_BRIDGE 4
typedef struct typedef struct
{ {
char *ifname; char *ifname;
@ -62,14 +71,38 @@ struct If_info
LIST_ENTRY(If_info) csm_next; 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 struct VLAN_ID
{ {
uint16_t vid; uint16_t vid;
uint16_t vlan_removed; uint16_t vlan_removed;
struct LocalInterface* vlan_itf; /* loacl vlan interface */ 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 struct PeerInterface
{ {
int ifindex; int ifindex;
@ -88,7 +121,7 @@ struct PeerInterface
struct CSM* csm; struct CSM* csm;
LIST_ENTRY(PeerInterface) mlacp_next; LIST_ENTRY(PeerInterface) mlacp_next;
LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list; struct vlan_rb_tree vlan_tree;
}; };
struct LocalInterface struct LocalInterface
@ -104,6 +137,8 @@ struct LocalInterface
uint8_t prefixlen; uint8_t prefixlen;
uint32_t ipv6_addr[4]; uint32_t ipv6_addr[4];
uint8_t prefixlen_v6; uint8_t prefixlen_v6;
uint32_t ipv6_ll_addr[4];
uint8_t ll_prefixlen_v6;
uint8_t l3_mode; uint8_t l3_mode;
uint8_t l3_mac_addr[ETHER_ADDR_LEN]; uint8_t l3_mac_addr[ETHER_ADDR_LEN];
@ -115,12 +150,18 @@ struct LocalInterface
int mlacp_state; /* Record mlacp state */ int mlacp_state; /* Record mlacp state */
uint8_t isolate_to_peer_link; uint8_t isolate_to_peer_link;
time_t po_down_time;
struct CSM* csm; struct CSM* csm;
uint8_t changed; uint8_t changed;
uint8_t port_config_sync; 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_next;
LIST_ENTRY(LocalInterface) system_purge_next; LIST_ENTRY(LocalInterface) system_purge_next;
@ -128,7 +169,7 @@ struct LocalInterface
LIST_ENTRY(LocalInterface) mlacp_purge_next; 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_name(const char* ifname);
struct LocalInterface* local_if_find_by_ifindex(int ifindex); struct LocalInterface* local_if_find_by_ifindex(int ifindex);
struct LocalInterface* local_if_find_by_po_id(int po_id); 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_init(struct LocalInterface*);
void local_if_finalize(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_create(struct CSM* csm, int peer_if_number, int type);
struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name); 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 iccp_get_server_sock_fd();
int scheduler_server_accept(); int scheduler_server_accept();
int iccp_receive_signal_handler(struct System* sys); int iccp_receive_signal_handler(struct System* sys);
void scheduler_csm_socket_cleanup(struct CSM* csm, int location);
#endif /* SCHEDULER_H_ */ #endif /* SCHEDULER_H_ */

View File

@ -34,6 +34,7 @@
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <linux/netlink.h>
#include "../include/port.h" #include "../include/port.h"
@ -52,6 +53,245 @@ struct CSM;
#define MAX_BUFSIZE 4096 #define MAX_BUFSIZE 4096
#endif #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 struct System
{ {
int server_fd;/* Peer-Link Socket*/ int server_fd;/* Peer-Link Socket*/
@ -78,6 +318,8 @@ struct System
LIST_HEAD(csm_list, CSM) csm_list; LIST_HEAD(csm_list, CSM) csm_list;
LIST_HEAD(lif_all_list, LocalInterface) lif_list; LIST_HEAD(lif_all_list, LocalInterface) lif_list;
LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_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 */ /* Settings */
char* log_file_path; char* log_file_path;
@ -91,13 +333,23 @@ struct System
time_t csm_trans_time; time_t csm_trans_time;
int need_sync_team_again; int need_sync_team_again;
int need_sync_netlink_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_create_csm();
struct CSM* system_get_csm_by_peer_ip(const char*); 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_csm_by_mlacp_id(int id);
struct CSM* system_get_first_csm();
struct System* system_get_instance(); struct System* system_get_instance();
void system_finalize(); void system_finalize();
void system_init(struct System*); 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_ */ #endif /* SYSTEM_H_ */

View File

@ -17,6 +17,7 @@ iccpd_SOURCES = \
mlacp_link_handler.c \ mlacp_link_handler.c \
mlacp_sync_prepare.c mlacp_sync_update.c\ mlacp_sync_prepare.c mlacp_sync_update.c\
mlacp_fsm.c \ mlacp_fsm.c \
iccp_netlink.c iccp_netlink.c \
openbsd_tree.c
iccpd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) iccpd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
iccpd_LDADD = -lnl-genl-3 -lnl-route-3 -lnl-3 -lpthread 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 (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*/ /*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; return 0;
} }
} }

View File

@ -52,10 +52,8 @@ int unset_mc_lag_id( struct CSM *csm, uint16_t id)
if (!csm) if (!csm)
return MCLAG_ERROR; return MCLAG_ERROR;
/* Mlag-ID, RG-ID, MLACP-ID*/ /* Remove ICCP info from STATE_DB */
csm->mlag_id = 0; mlacp_link_del_iccp_info(csm->mlag_id);
csm->iccp_info.icc_rg_id = 0;
csm->app_csm.mlacp.id = 0;
iccp_csm_finalize(csm); iccp_csm_finalize(csm);
@ -73,7 +71,9 @@ int set_peer_link(int mid, const char* ifname)
len = strlen(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); ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel or VTTNL(Vxlan tunnel)", ifname);
return MCLAG_ERROR; return MCLAG_ERROR;
@ -83,8 +83,11 @@ int set_peer_link(int mid, const char* ifname)
if (csm == NULL) if (csm == NULL)
return MCLAG_ERROR; 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; return MCLAG_ERROR;
}
if (strlen(csm->peer_itf_name) > 0) if (strlen(csm->peer_itf_name) > 0)
{ {
@ -114,7 +117,7 @@ int set_peer_link(int mid, const char* ifname)
csm->mlag_id, 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); memcpy(csm->peer_itf_name, ifname, len);
/* update peer-link link handler*/ /* 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) if (lif->type == IF_T_PORT_CHANNEL)
iccp_get_port_member_list(lif); iccp_get_port_member_list(lif);
set_peerlink_learn_kernel(csm, 0, 4);
} }
/*disconnect the link for mac and arp sync up*/ /*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) if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
{ {
/*must be enabled mac learn*/ /*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_mlag_port_learn(csm->peer_link_if, 1);
set_peerlink_learn_kernel(csm, 1, 5);
}
} }
/* update peer-link link handler*/ /* update peer-link link handler*/
scheduler_session_disconnect_handler(csm); scheduler_session_disconnect_handler(csm);
/* clean peer-link*/ /* 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) if (csm->peer_link_if)
{ {
csm->peer_link_if->is_peer_link = 0; csm->peer_link_if->is_peer_link = 0;
@ -282,6 +289,42 @@ int unset_peer_address(int mid)
return 0; 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) int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname)
{ {
struct CSM* csm = NULL; 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->po_id <= 0
|| lif_po->csm == NULL) || lif_po->csm == NULL)
{ {
if (lif_po)
{
ICCPD_LOG_DEBUG(__FUNCTION__, "CSM already detached for ifname = %s", lif_po->name);
}
return MCLAG_ERROR; return MCLAG_ERROR;
} }
/* find csm*/ /* find csm*/
csm = lif_po->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", ICCPD_LOG_DEBUG(__FUNCTION__, "Detach mclag id = %d from ifname = %s",
csm->mlag_id, lif_po->name); 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.*/ /* 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; unbind_poid = lif_po->po_id;
mlacp_unbind_local_if(lif_po); 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) if (strcmp(ifname, cif->name) == 0)
LIST_REMOVE(cif, csm_next); LIST_REMOVE(cif, csm_next);
} }
return 0; return 0;
} }

View File

@ -55,6 +55,21 @@ int set_mc_lag_by_id(uint16_t mid)
return ret; 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 #define CONFIG_LINE_LEN 512
int iccp_config_from_command(char * line) int iccp_config_from_command(char * line)

View File

@ -20,6 +20,7 @@
* *
* Maintainer: jianjun, grace Li from nephos * Maintainer: jianjun, grace Li from nephos
*/ */
#include <stdbool.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <ctype.h> #include <ctype.h>
#include <net/if.h> #include <net/if.h>
@ -33,6 +34,8 @@
#include "../include/iccp_cmd_show.h" #include "../include/iccp_cmd_show.h"
#include "../include/mlacp_link_handler.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) int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
{ {
struct mclagd_state state_info; struct mclagd_state state_info;
@ -67,6 +70,11 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
else else
state_info.keepalive = 0; 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 (mclag_id > 0)
{ {
if (csm->mlag_id == mclag_id) 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) if (peer_link_if)
memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6); 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(); logconfig = logger_get_configuration();
memcpy(state_info.loglevel, log_level_to_string(logconfig->log_level), strlen( log_level_to_string(logconfig->log_level))); 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; state_info.role = csm->role_type;
str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN; str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN;
len = 0;
LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next) 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; iccpd_arp = (struct ARPMsg*)msg->buf;
mclagd_arp.op_type = iccpd_arp->op_type; 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.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname));
memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16); memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16);
memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6); 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())) if (!(sys = system_get_instance()))
{ {
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
return EXEC_TYPE_NO_EXIST_SYS; 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; iccpd_ndisc = (struct NDISCMsg *)msg->buf;
mclagd_ndisc.op_type = iccpd_ndisc->op_type; 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.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.ipv6_addr, show_ipv6_str((char *)iccpd_ndisc->ipv6_addr), 46);
memcpy(mclagd_ndisc.mac_addr, iccpd_ndisc->mac_addr, 6); memcpy(mclagd_ndisc.mac_addr, iccpd_ndisc->mac_addr, 6);
memcpy(ndisc_buf + MCLAGD_REPLY_INFO_HDR + ndisc_num * 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));
&mclagd_ndisc, sizeof(struct mclagd_ndisc_msg));
ndisc_num++; ndisc_num++;
@ -302,14 +312,13 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id)
continue; 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)); 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.op_type = iccpd_mac->op_type;
mclagd_mac.fdb_type = iccpd_mac->fdb_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; mclagd_mac.vid = iccpd_mac->vid;
memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname)); 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)); 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 System *sys = NULL;
struct CSM *csm = NULL; struct CSM *csm = NULL;
struct LocalInterface *lif_po = NULL; struct LocalInterface *lif_po = NULL;
struct LocalInterface *lif_peer = NULL;
struct mclagd_local_if mclagd_lif; struct mclagd_local_if mclagd_lif;
struct VLAN_ID* vlan_id = NULL; struct VLAN_ID* vlan_id = NULL;
char * str_buf = 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) else if (lif_po->state == PORT_STATE_TEST)
memcpy(mclagd_lif.state, "Test", 4); 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.prefixlen = lif_po->prefixlen;
mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po); 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); memcpy(mclagd_lif.mlacp_state, "ERROR", 5);
mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link; 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; str_buf = mclagd_lif.vlanlist;
len = 0; len = 0;
LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next) int prev_vlan_id = 0;
{ int range = 0;
if (vlan_id != NULL ) int to_be_printed = 0;
RB_FOREACH (vlan_id, vlan_rb_tree, &(lif_po->vlan_tree))
{ {
if (str_size - len < 4) if (str_size - len < 4)
break; 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); 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; 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; *buf = lif_buf;
@ -473,6 +623,7 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id)
if (!(sys = system_get_instance())) if (!(sys = system_get_instance()))
{ {
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
return EXEC_TYPE_NO_EXIST_SYS; 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; 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) if (peer_if == NULL)
return -4; 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) peer_vlan = RB_FIND(vlan_rb_tree, &(peer_if->vlan_tree), local_vlan);
{
if (peer_vlan->vid == local_vlan->vid)
break;
}
if (peer_vlan == NULL) 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))
{ {
local_vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), peer_vlan);
LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next)
{
if (peer_vlan->vid == local_vlan->vid)
break;
}
if (local_vlan == NULL) if (local_vlan == NULL)
{ {

View File

@ -20,7 +20,7 @@
* *
* Maintainer: jianjun, grace Li from nephos * Maintainer: jianjun, grace Li from nephos
*/ */
#include <pthread.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
@ -29,6 +29,7 @@
#include "../include/scheduler.h" #include "../include/scheduler.h"
#include "../include/msg_format.h" #include "../include/msg_format.h"
#include "../include/iccp_csm.h" #include "../include/iccp_csm.h"
#include "../include/iccp_cli.h"
#include "../include/mlacp_link_handler.h" #include "../include/mlacp_link_handler.h"
/***************************************** /*****************************************
* Define * Define
@ -121,6 +122,8 @@ void iccp_csm_init(struct CSM* csm)
memset(csm->peer_ip, 0, INET_ADDRSTRLEN); memset(csm->peer_ip, 0, INET_ADDRSTRLEN);
memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME); memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME);
csm->iccp_info.icc_rg_id = 0x0; 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 */ /* 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->heartbeat_update_time = 0;
csm->peer_warm_reboot_time = 0; csm->peer_warm_reboot_time = 0;
csm->warm_reboot_disconn_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->role_type = STP_ROLE_NONE;
csm->sock_read_event_ptr = NULL; csm->sock_read_event_ptr = NULL;
csm->peer_link_if = NULL; csm->peer_link_if = NULL;
@ -165,6 +170,9 @@ void iccp_csm_finalize(struct CSM* csm)
{ {
struct If_info * cif = NULL; struct If_info * cif = NULL;
struct System* sys = NULL; struct System* sys = NULL;
struct LocalInterface* lifp = NULL;
struct LocalInterface* local_if = NULL;
struct LocalInterface* local_if_next = NULL;
if (csm == NULL) if (csm == NULL)
return; return;
@ -176,19 +184,38 @@ void iccp_csm_finalize(struct CSM* csm)
if (sys->warmboot_exit != WARM_REBOOT) if (sys->warmboot_exit != WARM_REBOOT)
{ {
/*Enable peer link port MAC learning*/ /*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_mlag_port_learn(csm->peer_link_if, 1);
set_peerlink_learn_kernel(csm, 1, 1);
}
} }
/* Disconnect from peer */ /* Disconnect from peer */
scheduler_session_disconnect_handler(csm); 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 */ /* Release all Connection State Machine instance */
app_csm_finalize(csm); app_csm_finalize(csm);
LIST_FOREACH(cif, &(csm->if_bind_list), csm_next) LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next)
{ {
LIST_REMOVE(cif, csm_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 */ /* Release iccp_csm */
@ -219,6 +246,8 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
{ {
LDPHdr* ldp_hdr = (LDPHdr*)buf; LDPHdr* ldp_hdr = (LDPHdr*)buf;
ICCParameter* param = NULL; ICCParameter* param = NULL;
ssize_t rc;
uint16_t tlv_type;
if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0) if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0)
return MCLAG_ERROR; return MCLAG_ERROR;
@ -228,7 +257,7 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
else else
param = (struct ICCParameter*)&buf[sizeof(ICCHdr)]; 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].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].type = ntohs(ldp_hdr->msg_type);
csm->msg_log.msg[csm->msg_log.end_index].tlv = ntohs(param->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) if (csm->msg_log.end_index >= 128)
csm->msg_log.end_index = 0; 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 */ /* Connection State Machine Transition */
@ -776,8 +818,34 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len)
return MCLAG_ERROR; 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) void iccp_csm_stp_role_count(struct CSM *csm)
{ {
struct If_info * cif = NULL;
/* decide the role, lower ip to be active & socket client*/ /* decide the role, lower ip to be active & socket client*/
if (csm->role_type == STP_ROLE_NONE) if (csm->role_type == STP_ROLE_NONE)
{ {
@ -786,12 +854,18 @@ void iccp_csm_stp_role_count(struct CSM *csm)
/* Active*/ /* Active*/
ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]"); ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]");
csm->role_type = STP_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 else
{ {
/* Standby*/ /* Standby*/
ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]"); ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]");
csm->role_type = STP_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) if (err == -1 && errno == EINTR)
goto retry; goto retry;
SYSTEM_INCR_WARMBOOT_COUNTER(sys);
return; 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_WARNING,
LOG_NOTICE, LOG_NOTICE,
LOG_INFO, LOG_INFO,
LOG_DEBUG, LOG_DEBUG
}; };
char* log_level_to_string(int level) char* log_level_to_string(int level)
@ -100,7 +100,7 @@ void log_finalize()
/*do nothing*/ /*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(); struct LoggerConfig* config = logger_get_configuration();
char buf[LOGBUF_SIZE]; char buf[LOGBUF_SIZE];

View File

@ -29,7 +29,11 @@
#include <errno.h> #include <errno.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "mclagdctl.h" #include "mclagdctl.h"
#include "../../include/mlacp_fsm.h"
#include "../../include/system.h"
static int mclagdctl_sock_fd = -1; static int mclagdctl_sock_fd = -1;
char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock"; 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: Already implemented command:
mclagdctl -i dump state mclagdctl -i dump state
mclagdctl -i dump arp mclagdctl -i dump arp
mclagdctl -i dump nd
mclagdctl -i dump mac mclagdctl -i dump mac
mclagdctl -i dump unique_ip
mclagdctl -i dump portlist local mclagdctl -i dump portlist local
mclagdctl -i dump portlist peer 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[] = static struct command_type command_types[] =
{ {
{ {
@ -83,6 +101,14 @@ static struct command_type command_types[] =
.enca_msg = mclagdctl_enca_dump_mac, .enca_msg = mclagdctl_enca_dump_mac,
.parse_msg = mclagdctl_parse_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, .id = ID_CMDTYPE_D_P,
.parent_id = ID_CMDTYPE_D, .parent_id = ID_CMDTYPE_D,
@ -104,6 +130,19 @@ static struct command_type command_types[] =
.enca_msg = mclagdctl_enca_dump_peer_portlist, .enca_msg = mclagdctl_enca_dump_peer_portlist,
.parse_msg = mclagdctl_parse_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, .id = ID_CMDTYPE_C,
.name = "config", .name = "config",
@ -250,8 +289,18 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
{ {
state_info = (struct mclagd_state*)(msg + len * count); 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) if (state_info->mclag_id <= 0)
fprintf(stdout, "%s: %s\n", "Domain id", "Unknown"); fprintf(stdout, "%s: %s\n", "Domain id", "Unknown");
else 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", "Local Ip", state_info->local_ip);
fprintf(stdout, "%s: %s\n", "Peer Ip", state_info->peer_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: %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", fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n",
"Peer Link Mac", "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[2], state_info->peer_link_mac[3],
state_info->peer_link_mac[4], state_info->peer_link_mac[5]); 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"); 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"); fprintf(stdout, "%s: %s\n", "Role", "Active");
else if (state_info->role == 2) else if (state_info->role == 2)
fprintf(stdout, "%s: %s\n", "Role", "Standby"); 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", "IP");
fprintf(stdout, "%-20s", "MAC"); fprintf(stdout, "%-20s", "MAC");
fprintf(stdout, "%-20s", "DEV"); fprintf(stdout, "%-20s", "DEV");
fprintf(stdout, "%s", "Flag");
fprintf(stdout, "\n"); fprintf(stdout, "\n");
len = sizeof(struct mclagd_arp_msg); 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]); arp_info->mac_addr[4], arp_info->mac_addr[5]);
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "%-20s", arp_info->ifname); 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"); fprintf(stdout, "\n");
} }
@ -360,6 +420,7 @@ int mclagdctl_parse_dump_ndisc(char *msg, int data_len)
fprintf(stdout, "%-52s", "IPv6"); fprintf(stdout, "%-52s", "IPv6");
fprintf(stdout, "%-20s", "MAC"); fprintf(stdout, "%-20s", "MAC");
fprintf(stdout, "%-20s", "DEV"); fprintf(stdout, "%-20s", "DEV");
fprintf(stdout, "%s", "Flag");
fprintf(stdout, "\n"); fprintf(stdout, "\n");
len = sizeof(struct mclagd_ndisc_msg); 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, "%-52s", ndisc_info->ipv6_addr);
fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x", fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x",
ndisc_info->mac_addr[0], ndisc_info->mac_addr[1], ndisc_info->mac_addr[0], ndisc_info->mac_addr[1],
ndisc_info->mac_addr[2], ndisc_info->mac_addr[3], ndisc_info->mac_addr[2], ndisc_info->mac_addr[3], ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]);
ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]);
fprintf(stdout, " "); fprintf(stdout, " ");
fprintf(stdout, "%-20s", ndisc_info->ifname); 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"); fprintf(stdout, "\n");
} }
@ -430,7 +497,8 @@ int mclagdctl_parse_dump_mac(char *msg, int data_len)
else else
fprintf(stdout, "%-5s", "D"); 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, "%-5d", mac_info->vid);
fprintf(stdout, "%-20s", mac_info->ifname); fprintf(stdout, "%-20s", mac_info->ifname);
fprintf(stdout, "%-20s", mac_info->origin_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", "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", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No");*/
fprintf(stdout, "%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf); 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: %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", "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); fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist);
} }
else 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", "Type", lif_info->type);
fprintf(stdout, "%s: %s\n", "PortName", lif_info->name); fprintf(stdout, "%s: %s\n", "PortName", lif_info->name);
fprintf(stdout, "%s: %s\n", "State", lif_info->state); 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);*/ /*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; 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) int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv)
{ {
struct mclagdctl_req_hdr req; struct mclagdctl_req_hdr req;
@ -940,4 +1281,3 @@ int main(int argc, char **argv)
return ret; return ret;
} }

View File

@ -17,7 +17,11 @@
* *
* Maintainer: Jim Jiang from nephos * 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_PARA1_LEN 16
#define MCLAGDCTL_PARA2_LEN 32 #define MCLAGDCTL_PARA2_LEN 32
#define MCLAGDCTL_PARA3_LEN 64 #define MCLAGDCTL_PARA3_LEN 64
@ -54,8 +58,11 @@ enum id_command_type
ID_CMDTYPE_D_P, ID_CMDTYPE_D_P,
ID_CMDTYPE_D_P_L, ID_CMDTYPE_D_P_L,
ID_CMDTYPE_D_P_P, ID_CMDTYPE_D_P_P,
ID_CMDTYPE_D_D,
ID_CMDTYPE_D_D_C,
ID_CMDTYPE_C, ID_CMDTYPE_C,
ID_CMDTYPE_C_L, ID_CMDTYPE_C_L,
ID_CMDTYPE_C_D,
}; };
enum mclagdctl_notify_peer_type enum mclagdctl_notify_peer_type
@ -65,9 +72,12 @@ enum mclagdctl_notify_peer_type
INFO_TYPE_DUMP_ARP, INFO_TYPE_DUMP_ARP,
INFO_TYPE_DUMP_NDISC, INFO_TYPE_DUMP_NDISC,
INFO_TYPE_DUMP_MAC, INFO_TYPE_DUMP_MAC,
INFO_TYPE_DUMP_UNIQUE_IP,
INFO_TYPE_DUMP_LOCAL_PORTLIST, INFO_TYPE_DUMP_LOCAL_PORTLIST,
INFO_TYPE_DUMP_PEER_PORTLIST, INFO_TYPE_DUMP_PEER_PORTLIST,
INFO_TYPE_DUMP_DBG_COUNTERS,
INFO_TYPE_CONFIG_LOGLEVEL, INFO_TYPE_CONFIG_LOGLEVEL,
INFO_TYPE_CONFIG_DOWN,
INFO_TYPE_FINISH, INFO_TYPE_FINISH,
}; };
@ -122,21 +132,28 @@ struct mclagd_state
{ {
int mclag_id; int mclag_id;
int keepalive; int keepalive;
int info_sync_done;
char local_ip[MCLAGDCTL_INET_ADDR_LEN]; char local_ip[MCLAGDCTL_INET_ADDR_LEN];
char peer_ip[MCLAGDCTL_INET_ADDR_LEN]; char peer_ip[MCLAGDCTL_INET_ADDR_LEN];
char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE]; char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE];
unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN]; unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN];
int role; int role;
char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN]; char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN];
int session_timeout;
int keepalive_time;
char loglevel[MCLAGDCTL_PARA1_LEN]; char loglevel[MCLAGDCTL_PARA1_LEN];
}; };
#define NEIGH_LOCAL 1
#define NEIGH_REMOTE 2
struct mclagd_arp_msg struct mclagd_arp_msg
{ {
char op_type; char op_type;
char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN]; char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN];
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
uint8_t learn_flag;
}; };
struct mclagd_ndisc_msg struct mclagd_ndisc_msg
@ -145,13 +162,14 @@ struct mclagd_ndisc_msg
char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
char ipv6_addr[MCLAGDCTL_INET6_ADDR_LEN]; char ipv6_addr[MCLAGDCTL_INET6_ADDR_LEN];
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN]; unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
uint8_t learn_flag;
}; };
struct mclagd_mac_msg struct mclagd_mac_msg
{ {
unsigned char op_type;/*add or del*/ unsigned char op_type;/*add or del*/
unsigned char fdb_type;/*static or dynamic*/ unsigned char fdb_type;/*static or dynamic*/
char mac_str[ETHER_ADDR_STR_LEN]; uint8_t mac_addr[ETHER_ADDR_LEN];
unsigned short vid; unsigned short vid;
/*Current if name that set in chip*/ /*Current if name that set in chip*/
char ifname[MCLAGDCTL_MAX_L_PORT_NANE]; char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
@ -178,7 +196,7 @@ struct mclagd_local_if
unsigned char po_active; unsigned char po_active;
char mlacp_state[MCLAGDCTL_PARA1_LEN]; char mlacp_state[MCLAGDCTL_PARA1_LEN];
unsigned char isolate_to_peer_link; unsigned char isolate_to_peer_link;
bool is_traffic_disable;
char vlanlist[MCLAGDCTL_PARA3_LEN]; char vlanlist[MCLAGDCTL_PARA3_LEN];
}; };
@ -193,6 +211,21 @@ struct mclagd_peer_if
unsigned char po_active; 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_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_parse_dump_state(char *msg, int data_len);
extern int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv); 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_enca_config_loglevel(char *msg, int log_level, int argc, char **argv);
int mclagdctl_parse_config_loglevel(char *msg, int data_len); 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 <msg_format.h>
#include <system.h> #include <system.h>
#include <logger.h> #include <logger.h>
#include <assert.h>
#include "../include/mlacp_tlv.h" #include "../include/mlacp_tlv.h"
#include "../include/mlacp_sync_prepare.h" #include "../include/mlacp_sync_prepare.h"
#include "../include/mlacp_link_handler.h" #include "../include/mlacp_link_handler.h"
#include "../include/mlacp_sync_update.h" #include "../include/mlacp_sync_update.h"
#include "../include/system.h"
#include "../include/scheduler.h"
#include <signal.h> #include <signal.h>
@ -58,6 +61,18 @@
TAILQ_INIT(&(list)); \ 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) \ #define PIF_QUEUE_REINIT(list) \
{ \ { \
while (!LIST_EMPTY(&(list))) { \ while (!LIST_EMPTY(&(list))) { \
@ -93,22 +108,48 @@
LIST_INIT(&(list)); \ 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 WARM_REBOOT_TIMEOUT 90
#define PEER_REBOOT_TIMEOUT 300
/***************************************** /*****************************************
* Static Function * 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_arp(struct CSM* csm);
static void mlacp_resync_ndisc(struct CSM* csm); static void mlacp_resync_ndisc(struct CSM *csm);
static void mlacp_resync_mac(struct CSM* csm);
/* Sync Sender APIs*/ /* Sync Sender APIs*/
static void mlacp_sync_send_sysConf(struct CSM* csm); static void mlacp_sync_send_sysConf(struct CSM* csm);
static void mlacp_sync_send_aggConf(struct CSM* csm); static void mlacp_sync_send_aggConf(struct CSM* csm);
static void mlacp_sync_send_aggState(struct CSM* csm); static void mlacp_sync_send_aggState(struct CSM* csm);
static void mlacp_sync_send_syncArpInfo(struct CSM* csm); static void mlacp_sync_send_syncArpInfo(struct CSM* csm);
static void mlacp_sync_send_syncNdiscInfo(struct CSM* csm); static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm);
static void mlacp_sync_send_heartbeat(struct CSM* csm); static void mlacp_sync_send_heartbeat(struct CSM* csm);
static void mlacp_sync_send_syncDoneData(struct CSM* csm); static void mlacp_sync_send_syncDoneData(struct CSM* csm);
/* Sync Reciever APIs*/ /* Sync Reciever APIs*/
@ -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_stage_handler(struct CSM* csm, struct Msg* msg);
static void mlacp_exchange_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 * 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) static void mlacp_sync_send_syncMacInfo(struct CSM* csm)
{ {
int msg_len = 0; int msg_len = 0;
struct Msg* msg = NULL; struct MACMsg* mac_msg = NULL;
struct MACMsg mac_find;
int count = 0; int count = 0;
memset(g_csm_buf, 0, CSM_BUFFER_SIZE); memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
memset(&mac_find, 0, sizeof(struct MACMsg));
while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list))) while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list)))
{ {
msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list)); mac_msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list));
TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail); 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, (struct MACMsg*)msg->buf, count);
msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, mac_msg, count);
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) if (count >= MAX_MAC_ENTRY_NUM)
{ {
iccp_csm_send(csm, g_csm_buf, msg_len); 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)); msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list));
TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail); 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++; count++;
free(msg->buf); free(msg->buf);
free(msg); free(msg);
@ -283,7 +349,7 @@ static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
msg = TAILQ_FIRST(&(MLACP(csm).ndisc_msg_list)); msg = TAILQ_FIRST(&(MLACP(csm).ndisc_msg_list));
TAILQ_REMOVE(&(MLACP(csm).ndisc_msg_list), msg, tail); 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++; count++;
free(msg->buf); free(msg->buf);
free(msg); free(msg);
@ -301,6 +367,7 @@ static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
return; return;
} }
static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm) static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm)
{ {
struct System* sys = NULL; struct System* sys = NULL;
@ -348,7 +415,7 @@ static void mlacp_sync_send_heartbeat(struct CSM* csm)
int msg_len = 0; int msg_len = 0;
if ((csm->heartbeat_send_time == 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); memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
msg_len = mlacp_prepare_for_heartbeat(csm, g_csm_buf, 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) if (mlacp_fsm_update_system_conf(csm, sysconf) == MCLAG_ERROR)
{ {
/*NOTE: we just change the node ID local side without sending NAK msg*/ /*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_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; 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) if (mlacp_fsm_update_Agg_conf(csm, portconf) == MCLAG_ERROR)
{ {
mlacp_sync_send_nak_handler(csm, msg); 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; 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_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.";*/ /*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; return;
@ -448,7 +544,12 @@ static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg)
{ {
/* Sync done*/ /* Sync done*/
MLACP(csm).wait_for_sync_data = 0; 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; 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_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)];
MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num); 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*/ /* Reply the peer all sync info*/
mlacp_sync_send_all_info_handler(csm); 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; 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) if (mlacp_fsm_update_port_channel_info(csm, portconf) == MCLAG_ERROR)
{ {
mlacp_sync_send_nak_handler(csm, msg); 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; return;
@ -485,6 +598,8 @@ static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg)
peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]); peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_peerlink_info( csm, peerlink); mlacp_fsm_update_peerlink_info( csm, peerlink);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
peerlink->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return; 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)]); mac_info = (struct mLACPMACInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_mac_info_from_peer(csm, mac_info); 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; 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)]); arp_info = (struct mLACPARPInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_arp_info(csm, arp_info); 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; return;
} }
@ -518,6 +637,7 @@ static void mlacp_sync_recv_ndiscInfo(struct CSM *csm, struct Msg *msg)
return; return;
} }
static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg) static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg)
{ {
/*Don't support currently*/ /*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)]); tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_heartbeat(csm, tlv); mlacp_fsm_update_heartbeat(csm, tlv);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return; return;
} }
@ -540,10 +662,102 @@ static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg)
tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]); tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]);
mlacp_fsm_update_warmboot(csm, tlv); mlacp_fsm_update_warmboot(csm, tlv);
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
return; 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 * 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).mlacp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_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).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); PIF_QUEUE_REINIT(MLACP(csm).pif_list);
LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_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*/ /* 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).arp_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_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); LIF_QUEUE_REINIT(MLACP(csm).lif_list);
MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK; 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).mlacp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_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).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).arp_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_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 */ /* remove lif & lif-purge queue */
LIF_QUEUE_REINIT(MLACP(csm).lif_list); 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).mlacp_msg_list);
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_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).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; 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; return;
} }
@ -657,6 +879,9 @@ void mlacp_fsm_transit(struct CSM* csm)
mlacp_sync_send_heartbeat(csm); mlacp_sync_send_heartbeat(csm);
mlacp_local_lif_state_mac_handler(csm);
mlacp_peer_link_learning_handler(csm);
/* Dequeue msg if any*/ /* Dequeue msg if any*/
while (have_msg) while (have_msg)
{ {
@ -728,7 +953,7 @@ void mlacp_fsm_transit(struct CSM* csm)
} }
/* Helper function for dumping application state machine */ /* Helper function for dumping application state machine */
static char* mlacp_state(struct CSM* csm) char* mlacp_state(struct CSM* csm)
{ {
if (csm == NULL ) if (csm == NULL )
return "MLACP_NULL"; return "MLACP_NULL";
@ -767,12 +992,6 @@ void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg)
if (msg == NULL ) if (msg == NULL )
return; 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); TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail);
return; return;
@ -792,32 +1011,77 @@ struct Msg* mlacp_dequeue_msg(struct CSM* csm)
return msg; return msg;
} }
/****************************************** void mlacp_sync_mac(struct CSM* csm)
* When peerlink ready, prepare the MACMsg
*
******************************************/
static void mlacp_resync_mac(struct CSM* csm)
{ {
struct Msg* msg = NULL;
struct MACMsg* mac_msg = NULL; struct MACMsg* mac_msg = NULL;
struct Msg *msg_send = NULL; RB_FOREACH (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb)
/* recover MAC info sync from peer*/
if (!TAILQ_EMPTY(&(MLACP(csm).mac_list)))
{ {
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; 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), mac_msg, tail);
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); 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 = (struct ARPMsg*)msg->buf;
arp_msg->op_type = NEIGH_SYNC_ADD; 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) 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); 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 = (struct NDISCMsg *)msg->buf;
ndisc_msg->op_type = NEIGH_SYNC_ADD; 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) 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); 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: case TLV_T_MLACP_WARMBOOT_FLAG:
mlacp_sync_recv_warmboot(csm, msg); mlacp_sync_recv_warmboot(csm, msg);
break; 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));*/ /*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); iccp_csm_send(csm, g_csm_buf, len);
/* Destroy old interface*/ /* Destroy old interface*/
if (lif_purge != NULL) 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); LIST_REMOVE(lif_purge, mlacp_purge_next);
} }
}
/* Send mlag lif*/ /* Send mlag lif*/
LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next) LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next)
{ {
if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync) 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*/ /* Send port channel information*/
memset(g_csm_buf, 0, CSM_BUFFER_SIZE); memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif, 0); 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*/ /* Send port channel state information*/
memset(g_csm_buf, 0, CSM_BUFFER_SIZE); memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif); 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; lif->changed = 0;
} }
} }
}
/* Send MAC info if any*/ /* Send MAC info if any*/
mlacp_sync_send_syncMacInfo(csm); mlacp_sync_send_syncMacInfo(csm);
@ -1291,3 +1580,90 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
return; 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->port_num_agg_id = 0;
tlv->actor_key = 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; 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 else
tlv->flags = htons(0x01); tlv->flags = htons(0x01);
ICCPD_LOG_DEBUG("ICCP_CSM", "TX sync %s", end ? "end" : "start");
return msg_len; 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); memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN);
tlv->sys_priority = htons(MLACP(csm).system_priority); tlv->sys_priority = htons(MLACP(csm).system_priority);
tlv->node_id = MLACP(csm).node_id; 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; 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->actor_key = 0;
tlv->agg_state = local_if->state; 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; 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->agg_name, lif->name, MAX_L_PORT_NAME);
memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN); 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; 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 = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * count];
MacData->type = mac_msg->op_type; 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); sprintf(MacData->ifname, "%s", mac_msg->origin_ifname);
MacData->vid = htons(mac_msg->vid); 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, 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_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count); mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count);
return msg_len; 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 * 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; struct mLACPARPInfoTLV* tlv = NULL;
size_t msg_len = 0; 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 = (struct ARPMsg *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * count];
ArpData->op_type = arp_msg->op_type; ArpData->op_type = arp_msg->op_type;
ArpData->flag = arp_msg->flag;
sprintf(ArpData->ifname, "%s", arp_msg->ifname); sprintf(ArpData->ifname, "%s", arp_msg->ifname);
ArpData->ipv4_addr = arp_msg->ipv4_addr; ArpData->ipv4_addr = arp_msg->ipv4_addr;
memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN); 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], 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",
ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5], show_ip_str(ArpData->ipv4_addr)); 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; 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 * 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; struct mLACPNDISCInfoTLV *tlv = NULL;
size_t msg_len = 0; size_t msg_len = 0;
size_t tlv_len = 0; size_t tlv_len = 0;
ICCHdr *icc_hdr = NULL; ICCHdr *icc_hdr = NULL;
struct NDISCMsg *NdiscData; struct NDISCMsg *NdiscData = NULL;
if (!csm) if (!csm)
return -1; 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); 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->op_type = ndisc_msg->op_type;
NdiscData->flag = ndisc_msg->flag;
sprintf(NdiscData->ifname, "%s", ndisc_msg->ifname); 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); 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[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)); 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; return MCLAG_ERROR;
/* Calculate VLAN ID Length */ /* 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) if (vlan_id != NULL)
num_of_vlan_id++; 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); tlv->num_of_vlan_id = htons(num_of_vlan_id);
num_of_vlan_id = 0; 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 ) 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(__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; 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); memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME);
tlv->port_type = peerlink_port->type; 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; 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->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter));
tlv->warmboot = 0x1; 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; 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/port.h"
#include "../include/system.h" #include "../include/system.h"
#include "../include/iccp_csm.h" #include "../include/iccp_csm.h"
#include "../include/iccp_netlink.h" #include "../include/mlacp_link_handler.h"
#include "../include/scheduler.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) 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_peer_link = 0;
local_if->is_arp_accept = 0; local_if->is_arp_accept = 0;
local_if->l3_mode = 0; local_if->l3_mode = 0;
local_if->master_ifindex = 0;
local_if->state = PORT_STATE_DOWN; local_if->state = PORT_STATE_DOWN;
local_if->prefixlen = 32; local_if->prefixlen = 32;
local_if->csm = NULL; local_if->csm = NULL;
local_if->isolate_to_peer_link = 0; 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; return;
} }
@ -64,7 +82,7 @@ void vlan_info_init(struct VLAN_ID* vlan)
return; 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 System* sys = NULL;
struct LocalInterface* local_if = 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())) if (!(sys = system_get_instance()))
return NULL; return NULL;
if (ifindex < 0) if (ifindex > 0) {
return NULL;
if ((local_if = local_if_find_by_ifindex(ifindex))) if ((local_if = local_if_find_by_ifindex(ifindex)))
return local_if; return local_if;
}
if (!(local_if = (struct LocalInterface*)malloc(sizeof(struct LocalInterface)))) 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_init(local_if);
local_if->ifindex = ifindex; local_if->ifindex = ifindex;
local_if->type = type; local_if->type = type;
local_if->state = state;
local_if->po_down_time = 0;
if (local_if->type == IF_T_PORT_CHANNEL) 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; return NULL;
local_if->po_id = atoi(&ifname[i]); local_if->po_id = atoi(&ifname[i]);
local_if->po_active = (state == PORT_STATE_UP) ? 1 : 0;
} }
if (ifname) if (ifname)
@ -121,7 +142,10 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
break; break;
case IF_T_VLAN: case IF_T_VLAN:
/* do nothing currently. */ if(is_unique_ip_configured(local_if->name))
{
local_if->is_l3_proto_enabled = true;
}
break; break;
case IF_T_VXLAN: 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); 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*/ /*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/
/*When set peer-link, the local-if is probably not created*/ /*When set peer-link, the local-if is probably not created*/
LIST_FOREACH(csm, &(sys->csm_list), next) 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; local_if->is_peer_link = 1;
csm->peer_link_if = local_if; csm->peer_link_if = local_if;
set_peerlink_learn_kernel(csm, 0, 3);
break; break;
} }
/*check the intf is bind with csm*/ /*check the intf is bind with csm*/
@ -217,21 +245,37 @@ struct LocalInterface* local_if_find_by_po_id(int po_id)
return NULL; 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 System *sys = NULL;
struct LocalInterface *lif = NULL; struct LocalInterface *lif = NULL;
struct VLAN_ID *vlan = 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) if ((sys = system_get_instance()) != NULL)
{ {
LIST_FOREACH(lif, &(sys->lif_list), system_next) LIST_FOREACH(lif, &(sys->lif_list), system_next)
{ {
LIST_FOREACH(vlan, &(lif->vlan_list), port_next) if (lif->type == IF_T_VLAN)
{
if (lif_vlan != vlan->vlan_itf)
continue; 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; vlan->vlan_itf = NULL;
} }
} }
@ -279,6 +323,7 @@ void local_if_destroy(char *ifname)
{ {
struct LocalInterface* lif = NULL; struct LocalInterface* lif = NULL;
struct CSM *csm = NULL; struct CSM *csm = NULL;
struct CSM *peer_ifname_csm = NULL;
struct System *sys = NULL; struct System *sys = NULL;
if (!(sys = system_get_instance())) if (!(sys = system_get_instance()))
@ -297,21 +342,27 @@ void local_if_destroy(char *ifname)
else else
local_if_remove(lif); local_if_remove(lif);
csm = lif->csm; //handle peer_link del case
if (csm && csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0) if ( (peer_ifname_csm = system_get_csm_by_peer_ifname(ifname)) != NULL )
{ {
/*if the peerlink interface is not created, peer connection can not establish*/ /*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->is_peer_link = 0;
csm->peer_link_if = NULL; csm->peer_link_if = NULL;
#endif
} }
csm = lif->csm;
if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE) if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
goto to_mlacp_purge; goto to_mlacp_purge;
else else
goto to_sys_purge; goto to_sys_purge;
to_sys_purge: to_sys_purge:
/* sys purge */ /* sys purge */
LIST_REMOVE(lif, system_next); LIST_REMOVE(lif, system_next);
if (lif->csm) if (lif->csm)
@ -319,7 +370,7 @@ void local_if_destroy(char *ifname)
LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next); LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next);
return; return;
to_mlacp_purge: to_mlacp_purge:
/* sys & mlacp purge */ /* sys & mlacp purge */
LIST_REMOVE(lif, system_next); LIST_REMOVE(lif, system_next);
LIST_REMOVE(lif, mlacp_next); LIST_REMOVE(lif, mlacp_next);
@ -336,8 +387,11 @@ int local_if_is_l3_mode(struct LocalInterface* local_if)
if (local_if == NULL) if (local_if == NULL)
return 0; 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; ret = 1;
}
return ret; return ret;
} }
@ -361,6 +415,25 @@ void local_if_change_flag_clear(void)
return; 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) void local_if_purge_clear(void)
{ {
struct System* sys = NULL; struct System* sys = NULL;
@ -375,8 +448,7 @@ void local_if_purge_clear(void)
lif = LIST_FIRST(&(sys->lif_purge_list)); lif = LIST_FIRST(&(sys->lif_purge_list));
ICCPD_LOG_DEBUG(__FUNCTION__, "Purge %s", lif->name); ICCPD_LOG_DEBUG(__FUNCTION__, "Purge %s", lif->name);
LIST_REMOVE(lif, system_purge_next); LIST_REMOVE(lif, system_purge_next);
if (lif->mlacp_purge_next.le_next != 0 && lif->mlacp_purge_next.le_prev != 0) local_if_mlacp_purge_del(lif);
LIST_REMOVE(lif, mlacp_purge_next);
local_if_del_all_vlan(lif); local_if_del_all_vlan(lif);
free(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) 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)); VLAN_RB_REMOVE(vlan_rb_tree, &(pif->vlan_tree), vlan);
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", free(vlan);
pif->name, pvlan->vid);
LIST_REMOVE(pvlan, port_next);
free(pvlan);
} }
return; return;
} }
@ -500,16 +570,15 @@ void peer_if_destroy(struct PeerInterface* pif)
int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid) int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid)
{ {
struct VLAN_ID *vlan = NULL; struct VLAN_ID *vlan = NULL;
struct VLAN_ID vlan_key = { 0 };
char vlan_name[16] = ""; char vlan_name[16] = "";
sprintf(vlan_name, "Vlan%d", vid); sprintf(vlan_name, "Vlan%d", vid);
/* traverse 1 time */ memset(&vlan_key, 0, sizeof(struct VLAN_ID));
LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) vlan_key.vid = vid;
{
if (vlan->vid == vid) vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), &vlan_key);
break;
}
if (!vlan) if (!vlan)
{ {
@ -517,53 +586,67 @@ int local_if_add_vlan(struct LocalInterface* local_if, uint16_t vid)
if (!vlan) if (!vlan)
return MCLAG_ERROR; 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_info_init(vlan);
vlan->vid = vid; vlan->vid = vid;
vlan->vlan_removed = 0;
vlan->vlan_itf = local_if_find_by_name(vlan_name); 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; return 0;
} }
void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid) void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid)
{ {
struct VLAN_ID *vlan = NULL; struct VLAN_ID *vlan = NULL;
struct VLAN_ID vlan_key = { 0 };
/* traverse 1 time */ memset(&vlan_key, 0, sizeof(struct VLAN_ID));
LIST_FOREACH(vlan, &(local_if->vlan_list), port_next) vlan_key.vid = vid;
{
if (vlan->vid == vid) vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), &vlan_key);
break;
}
if (vlan != NULL) if (vlan != NULL)
{ {
LIST_REMOVE(vlan, port_next); VLAN_RB_REMOVE(vlan_rb_tree, &(local_if->vlan_tree), vlan);
free(vlan); free(vlan);
local_if->port_config_sync = 1; 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; return;
} }
void local_if_del_all_vlan(struct LocalInterface* lif) void local_if_del_all_vlan(struct LocalInterface* lif)
{ {
struct VLAN_ID* vlan = NULL; 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)); VLAN_RB_REMOVE(vlan_rb_tree, &(lif->vlan_tree), vlan);
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid); lif->vlan_count -=1;
LIST_REMOVE(vlan, port_next);
free(vlan); 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) int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id)
{ {
struct VLAN_ID *peer_vlan = NULL; struct VLAN_ID *peer_vlan = NULL;
struct VLAN_ID vlan_key = { 0 };
char vlan_name[16] = ""; char vlan_name[16] = "";
sprintf(vlan_name, "Vlan%d", vlan_id); sprintf(vlan_name, "Vlan%d", vlan_id);
/* traverse 1 time */ memset(&vlan_key, 0, sizeof(struct VLAN_ID));
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next) vlan_key.vid = vlan_id;
{
if (peer_vlan->vid == vlan_id) peer_vlan = RB_FIND(vlan_rb_tree, &(peer_if->vlan_tree), &vlan_key);
{
ICCPD_LOG_DEBUG(__FUNCTION__, "Update VLAN ID %d for peer intf %s", peer_vlan->vid, peer_if->name);
break;
}
}
if (!peer_vlan) if (!peer_vlan)
{ {
@ -594,14 +673,14 @@ int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id)
if (!peer_vlan) if (!peer_vlan)
return MCLAG_ERROR; 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); vlan_info_init(peer_vlan);
peer_vlan->vid = vlan_id; 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; 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 = NULL;
struct VLAN_ID *peer_vlan_next = NULL; struct VLAN_ID *peer_vlan_next = NULL;
struct VLAN_ID *vlan_temp = NULL;
/* traverse 1 time */ /* 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) if (peer_vlan != NULL)
{ {
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid); 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); free(peer_vlan);
peer_vlan = NULL; peer_vlan = NULL;
@ -629,7 +709,7 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if)
if (peer_vlan != NULL) if (peer_vlan != NULL)
{ {
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid); 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); free(peer_vlan);
} }
@ -660,9 +740,32 @@ int set_sys_arp_accept_flag(char* ifname, int flag)
memset(cmd, 0, 64); memset(cmd, 0, 64);
snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname); snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname);
if (system(cmd)) 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); fclose(file_ptr);
return result; 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) static int session_conn_thread_lock(pthread_mutex_t *conn_mutex)
{ {
return 1; /*pthread_mutex_lock(conn_mutex);*/ return 1; /*pthread_mutex_lock(conn_mutex);*/
@ -71,10 +79,10 @@ static void heartbeat_check(struct CSM *csm)
return; return;
} }
if ( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC) if ( (time(NULL) - csm->heartbeat_update_time) > csm->session_timeout)
{ {
/* hearbeat 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); scheduler_session_disconnect_handler(csm);
} }
@ -106,15 +114,13 @@ static int scheduler_transit_fsm()
iccp_csm_transit(csm); iccp_csm_transit(csm);
app_csm_transit(csm); app_csm_transit(csm);
mlacp_fsm_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(); local_if_purge_clear();
return 1; return 1;
@ -131,6 +137,9 @@ int scheduler_csm_read_callback(struct CSM* csm)
size_t data_len = 0; size_t data_len = 0;
size_t pos = 0; size_t pos = 0;
int recv_len = 0, len = 0, retval; 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) if (csm->sock_fd <= 0)
return MCLAG_ERROR; return MCLAG_ERROR;
@ -138,6 +147,7 @@ int scheduler_csm_read_callback(struct CSM* csm)
memset(peer_msg, 0, CSM_BUFFER_SIZE); memset(peer_msg, 0, CSM_BUFFER_SIZE);
recv_len = 0; recv_len = 0;
errno = 0;
while (recv_len != sizeof(LDPHdr)) while (recv_len != sizeof(LDPHdr))
{ {
@ -145,38 +155,92 @@ int scheduler_csm_read_callback(struct CSM* csm)
if (len == -1) if (len == -1)
{ {
perror("recv(). Error"); 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; goto recv_err;
} }
else if (len == 0) 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; goto recv_err;
} }
recv_len += len; recv_len += len;
/*usleep(100);*/ /*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; 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; pos = 0;
while (data_len > 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) 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; 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) 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; goto recv_err;
} }
data_len -= recv_len; data_len -= recv_len;
pos += recv_len; pos += recv_len;
/*usleep(100);*/ /*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); 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) if (retval == 0)
{ {
@ -224,21 +288,21 @@ int scheduler_server_accept()
if (!csm) if (!csm)
{ {
/* can't find csm with peer ip*/ /* 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; goto reject_client;
} }
if (csm->sock_fd > 0) if (csm->sock_fd > 0)
{ {
/* peer already connected*/ /* 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; goto reject_client;
} }
if ((ret = scheduler_check_csm_config(csm)) < 0) if ((ret = scheduler_check_csm_config(csm)) < 0)
{ {
/* csm config error*/ /* 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; goto reject_client;
} }
} }
@ -257,6 +321,8 @@ int scheduler_server_accept()
struct epoll_event event; struct epoll_event event;
int err; 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.data.fd = new_fd;
event.events = EPOLLIN; event.events = EPOLLIN;
err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event); 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; 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; csm->current_state = ICCP_NONEXISTENT;
FD_SET(new_fd, &(sys->readfd)); FD_SET(new_fd, &(sys->readfd));
sys->readfd_count++; sys->readfd_count++;
@ -293,6 +367,8 @@ void iccp_get_start_type(struct System* sys)
if (strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm")) if (strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm"))
sys->warmboot_start = WARM_REBOOT; sys->warmboot_start = WARM_REBOOT;
ICCPD_LOG_DEBUG("ICCP_FSM", "Start ICCP: warm reboot %s",
(sys->warmboot_start == WARM_REBOOT)? "yes" : "no");
return; return;
} }
@ -309,6 +385,8 @@ void scheduler_init()
iccp_sys_local_if_list_get_init(); iccp_sys_local_if_list_get_init();
iccp_sys_local_if_list_get_addr(); iccp_sys_local_if_list_get_addr();
/*Interfaces must be created before this func called*/ /*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); iccp_config_from_file(sys->config_file_path);
/*Get kernel ARP info */ /*Get kernel ARP info */
@ -331,7 +409,6 @@ void scheduler_init()
return; return;
} }
extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size);
void mlacp_sync_send_warmboot_flag() void mlacp_sync_send_warmboot_flag()
{ {
struct System* sys = NULL; struct System* sys = NULL;
@ -350,7 +427,7 @@ void mlacp_sync_send_warmboot_flag()
iccp_csm_send(csm, g_csm_buf, msg_len); iccp_csm_send(csm, g_csm_buf, msg_len);
} }
} }
ICCPD_LOG_DEBUG("ICCP_FSM", "Send warmboot flag to peer. Start warmboot");
return; return;
} }
@ -542,12 +619,23 @@ void session_client_conn_handler(struct CSM *csm)
/* Conn OK*/ /* Conn OK*/
struct epoll_event event; struct epoll_event event;
int err; 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.data.fd = connFd;
event.events = EPOLLIN; event.events = EPOLLIN;
err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event); err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event);
if (err) if (err)
goto conn_fail; goto conn_fail;
csm->sock_fd = connFd; 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)); FD_SET(connFd, &(sys->readfd));
sys->readfd_count++; sys->readfd_count++;
ICCPD_LOG_INFO(__FUNCTION__, "Connect to server %s sucess .", csm->peer_ip); 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; lif->is_peer_link = 1;
csm->peer_link_if = lif; 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) void scheduler_session_disconnect_handler(struct CSM* csm)
{ {
struct System* sys = NULL; struct System* sys = NULL;
struct If_info * cif = NULL;
if ((sys = system_get_instance()) == NULL ) if ((sys = system_get_instance()) == NULL )
return; return;
struct epoll_event event;
if (csm == NULL) if (csm == NULL)
return; return;
ICCPD_LOG_NOTICE("ICCP_FSM", "scheduler session disconnect handler");
session_conn_thread_lock(&csm->conn_mutex); session_conn_thread_lock(&csm->conn_mutex);
scheduler_unregister_sock_read_event_callback(csm); scheduler_unregister_sock_read_event_callback(csm);
if (csm->sock_fd > 0) if (csm->sock_fd > 0)
{ {
event.data.fd = csm->sock_fd; scheduler_csm_socket_cleanup(csm, 1);
event.events = EPOLLIN;
epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event);
close(csm->sock_fd);
csm->sock_fd = -1;
} }
mlacp_peer_disconn_handler(csm); mlacp_peer_disconn_handler(csm);
MLACP(csm).current_state = MLACP_STATE_INIT; MLACP(csm).current_state = MLACP_STATE_INIT;
iccp_csm_status_reset(csm, 0); iccp_csm_status_reset(csm, 0);
time(&csm->connTimePrev); time(&csm->connTimePrev);
session_conn_thread_unlock(&csm->conn_mutex); session_conn_thread_unlock(&csm->conn_mutex);
return; 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 <stdio.h>
#include <netlink/msg.h>
#include "../include/iccp_csm.h" #include "../include/iccp_csm.h"
#include "../include/logger.h" #include "../include/logger.h"
#include "../include/iccp_netlink.h" #include "../include/iccp_netlink.h"
#include "../include/scheduler.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 */ /* Singleton */
struct System* system_get_instance() struct System* system_get_instance()
@ -53,6 +59,7 @@ void system_init(struct System* sys)
if (sys == NULL ) if (sys == NULL )
return; return;
memset(sys, 0, sizeof(struct System));
sys->server_fd = -1; sys->server_fd = -1;
sys->sync_fd = -1; sys->sync_fd = -1;
sys->sync_ctrl_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->csm_list));
LIST_INIT(&(sys->lif_list)); LIST_INIT(&(sys->lif_list));
LIST_INIT(&(sys->lif_purge_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->log_file_path = strdup("/var/log/iccpd.log");
sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty"); sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty");
@ -88,15 +97,21 @@ void system_finalize()
struct System* sys = NULL; struct System* sys = NULL;
struct CSM* csm = NULL; struct CSM* csm = NULL;
struct LocalInterface* local_if = NULL; struct LocalInterface* local_if = NULL;
struct Unq_ip_If_info* unq_ip_if = NULL;
if ((sys = system_get_instance()) == NULL ) if ((sys = system_get_instance()) == NULL )
return; 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))) while (!LIST_EMPTY(&(sys->csm_list)))
{ {
csm = LIST_FIRST(&(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); iccp_csm_finalize(csm);
} }
@ -115,6 +130,16 @@ void system_finalize()
local_if_finalize(local_if); 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(); iccp_system_dinit_netlink_socket();
if (sys->log_file_path != NULL ) if (sys->log_file_path != NULL )
@ -185,6 +210,34 @@ struct CSM* system_get_csm_by_peer_ip(const char* peer_ip)
return NULL; 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 CSM* system_get_csm_by_mlacp_id(int id)
{ {
struct System* sys = NULL; struct System* sys = NULL;
@ -201,3 +254,146 @@ struct CSM* system_get_csm_by_mlacp_id(int id)
return NULL; 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;
}
}