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:
parent
d26307d80f
commit
82b6bcfbb3
@ -36,10 +36,10 @@ typedef enum
|
||||
|
||||
typedef struct cli_param_queue
|
||||
{
|
||||
char ifname[16];
|
||||
char ifname[16];
|
||||
cli_queue_type_et type;
|
||||
int param;
|
||||
int itf_add;
|
||||
int param;
|
||||
int itf_add;
|
||||
LIST_ENTRY(cli_param_queue) cli_queue_next;
|
||||
} cli_param_queue_st;
|
||||
|
||||
@ -50,18 +50,21 @@ typedef struct cli_param_queue
|
||||
#define MCLAG_INTF_STR "mclag_interface"
|
||||
#define SYSTEM_MAC_STR "system_mac"
|
||||
|
||||
int set_mc_lag_id(struct CSM* csm, uint16_t domain);
|
||||
int set_peer_link(int mid, const char* ifname);
|
||||
int set_local_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 set_mc_lag_id(struct CSM *csm, uint16_t domain);
|
||||
int set_peer_link(int mid, const char *ifname);
|
||||
int set_local_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_peer_link(int mid);
|
||||
int unset_local_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_detach_mclag_domain_to_port_channel(const char* ifname);
|
||||
int set_local_system_id(const char* mac);
|
||||
int unset_local_system_id( );
|
||||
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 set_local_system_id(const char *mac);
|
||||
int unset_local_system_id();
|
||||
|
||||
int set_keepalive_time(int mid, int keepalive_time);
|
||||
int set_session_timeout(int mid, int session_timeout_val);
|
||||
|
||||
#endif
|
||||
|
@ -26,4 +26,7 @@
|
||||
|
||||
int iccp_config_from_file(char *config_default_dir);
|
||||
|
||||
int set_mc_lag_by_id(uint16_t mid);
|
||||
int unset_mc_lag_by_id(uint16_t mid);
|
||||
|
||||
#endif /* ICCP_CMD_H_ */
|
||||
|
@ -33,4 +33,6 @@ extern int iccp_ndisc_dump(char * *buf, int *num, int mclag_id);
|
||||
extern int iccp_mac_dump(char * *buf, int *num, int mclag_id);
|
||||
extern int iccp_local_if_dump(char * *buf, int *num, int mclag_id);
|
||||
extern int iccp_peer_if_dump(char * *buf, int *num, int mclag_id);
|
||||
extern int iccp_cmd_dbg_counter_dump(char * *buf, int *data_len, int mclag_id);
|
||||
extern int iccp_unique_ip_if_dump(char * *buf, int *num, int mclag_id);
|
||||
#endif
|
||||
|
@ -45,10 +45,10 @@
|
||||
|
||||
#ifndef INET_ADDRSTRLEN
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#endif /* INET_ADDRSTRLEN */
|
||||
#endif /* INET_ADDRSTRLEN */
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
#endif /* INET6_ADDRSTRLEN */
|
||||
#endif /* INET6_ADDRSTRLEN */
|
||||
/* For socket binding */
|
||||
#define ICCP_TCP_PORT 8888
|
||||
#define MAX_ACCEPT_CONNETIONS 20
|
||||
@ -113,10 +113,15 @@ struct CSM
|
||||
time_t peer_warm_reboot_time;
|
||||
time_t warm_reboot_disconn_time;
|
||||
char peer_itf_name[IFNAMSIZ];
|
||||
time_t peer_link_learning_retry_time;
|
||||
char peer_ip[INET_ADDRSTRLEN];
|
||||
char sender_ip[INET_ADDRSTRLEN];
|
||||
void* sock_read_event_ptr;
|
||||
|
||||
int keepalive_time;
|
||||
int session_timeout;
|
||||
int peer_link_learning_enable;
|
||||
|
||||
/* Msg queue */
|
||||
TAILQ_HEAD(msg_list, Msg) msg_list;
|
||||
|
||||
@ -164,5 +169,5 @@ void iccp_csm_correspond_from_rg_connect_msg(struct CSM*, struct Msg*);
|
||||
void iccp_csm_correspond_from_rg_disconnect_msg(struct CSM*, struct Msg*);
|
||||
|
||||
int mlacp_bind_port_channel_to_csm(struct CSM* csm, const char *ifname);
|
||||
|
||||
int iccp_csm_init_mac_msg(struct MACMsg **mac_msg, char* data, int len);
|
||||
#endif /* ICCP_CSM_H_ */
|
||||
|
@ -37,6 +37,8 @@ int do_one_neigh_request(struct nlmsghdr *n);
|
||||
|
||||
void iccp_from_netlink_port_state_handler( char * ifname, int state);
|
||||
|
||||
void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n);
|
||||
void vlan_mbrship_change_handler(unsigned int vlan_id, char *mbr_if_name, int add_flag);
|
||||
void del_all_pending_vlan_mbr_ifs(struct System *sys);
|
||||
void move_pending_vlan_mbr_to_lif(struct System *sys, struct LocalInterface* lif);
|
||||
#endif // LACP_IFM_H
|
||||
|
||||
|
@ -26,9 +26,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <netlink/netlink.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "../include/system.h"
|
||||
#include "../include/port.h"
|
||||
#include <netinet/icmp6.h>
|
||||
@ -37,6 +35,7 @@
|
||||
#define NDISC_NEIGHBOUR_ADVERTISEMENT 136
|
||||
#define ND_OPT_TARGET_LL_ADDR 2
|
||||
#define NEXTHDR_ICMP 58
|
||||
#define ICCP_NLE_SEQ_MISMATCH -16
|
||||
|
||||
struct nd_msg
|
||||
{
|
||||
@ -51,17 +50,20 @@ struct in6_pktinfo
|
||||
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_dellink(struct nl_object *obj, void *arg);
|
||||
int iccp_system_init_netlink_socket();
|
||||
void iccp_system_dinit_netlink_socket();
|
||||
int iccp_init_netlink_event_fd(struct System *sys);
|
||||
int iccp_handle_events(struct System * sys);
|
||||
void update_if_ipmac_on_standby(struct LocalInterface* lif_po);
|
||||
int iccp_handle_events(struct System *sys);
|
||||
void update_if_ipmac_on_standby(struct LocalInterface *lif_po, int dir);
|
||||
int iccp_sys_local_if_list_get_addr();
|
||||
int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname);
|
||||
int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname, int permanent, int dir);
|
||||
int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif);
|
||||
|
||||
void recover_if_ipmac_on_standby(struct LocalInterface* lif_po, int dir);
|
||||
void update_vlan_if_mac_on_standby(struct LocalInterface* lif_vlan, int dir);
|
||||
void recover_vlan_if_mac_on_standby(struct LocalInterface* lif_vlan, int dir, uint8_t *remote_system_mac);
|
||||
void update_vlan_if_mac_on_iccp_up(struct LocalInterface* lif_peer, int is_up, uint8_t *remote_system_mac);
|
||||
#endif
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
typedef enum _iccpd_log_level_t
|
||||
{
|
||||
CRITICAL_LOG_LEVEL = 0,
|
||||
ERR_LOG_LEVEL = 1,
|
||||
ERR_LOG_LEVEL = 1,
|
||||
WARN_LOG_LEVEL = 2,
|
||||
NOTICE_LOG_LEVEL = 3,
|
||||
INFO_LOG_LEVEL = 4,
|
||||
|
@ -26,9 +26,12 @@
|
||||
#define _MLACP_FSM_H
|
||||
|
||||
#include "../include/port.h"
|
||||
#include "../include/mlacp_tlv.h"
|
||||
|
||||
#define MLCAP_SYNC_PHY_DEV_SEC 1 /*every 1 sec*/
|
||||
|
||||
#define MLACP_LOCAL_IF_DOWN_TIMER 600 // 600 seconds.
|
||||
|
||||
#define MLACP(csm_ptr) (csm_ptr->app_csm.mlacp)
|
||||
|
||||
struct CSM;
|
||||
@ -47,7 +50,7 @@ typedef enum MLACP_APP_STATE MLACP_APP_STATE_E;
|
||||
/* for sender only*/
|
||||
enum MLACP_SYNC_STATE
|
||||
{
|
||||
MLACP_SYNC_SYSCONF=0,
|
||||
MLACP_SYNC_SYSCONF = 0,
|
||||
MLACP_SYNC_AGGCONF,
|
||||
MLACP_SYNC_AGGSTATE,
|
||||
MLACP_SYNC_AGGINFO,
|
||||
@ -66,6 +69,85 @@ struct Remote_System
|
||||
uint32_t node_id;
|
||||
};
|
||||
|
||||
/****************************************************************
|
||||
* Debug counters to track message sent and received between
|
||||
* MC-LAG peers over ICCP
|
||||
***************************************************************/
|
||||
typedef uint8_t ICCP_DBG_CNTR_DIR_e;
|
||||
enum ICCP_DBG_CNTR_DIR_e
|
||||
{
|
||||
ICCP_DBG_CNTR_DIR_TX = 0,
|
||||
ICCP_DBG_CNTR_DIR_RX = 1,
|
||||
ICCP_DBG_CNTR_DIR_MAX
|
||||
};
|
||||
|
||||
typedef uint8_t ICCP_DBG_CNTR_STS_e;
|
||||
enum ICCP_DBG_CNTR_STS_e
|
||||
{
|
||||
ICCP_DBG_CNTR_STS_OK = 0,
|
||||
ICCP_DBG_CNTR_STS_ERR = 1, /* Send error or receive processing error*/
|
||||
ICCP_DBG_CNTR_STS_MAX
|
||||
};
|
||||
|
||||
/* Change MCLAGDCTL_MAX_DBG_COUNTERS if ICCP_DBG_CNTR_MSG_MAX is more than 32 */
|
||||
enum ICCP_DBG_CNTR_MSG
|
||||
{
|
||||
ICCP_DBG_CNTR_MSG_SYS_CONFIG = 0,
|
||||
ICCP_DBG_CNTR_MSG_AGGR_CONFIG = 1,
|
||||
ICCP_DBG_CNTR_MSG_AGGR_STATE = 2,
|
||||
ICCP_DBG_CNTR_MSG_MAC_INFO = 3,
|
||||
ICCP_DBG_CNTR_MSG_ARP_INFO = 4,
|
||||
ICCP_DBG_CNTR_MSG_L2MC_INFO = 5,
|
||||
ICCP_DBG_CNTR_MSG_PORTCHANNEL_INFO = 6,
|
||||
ICCP_DBG_CNTR_MSG_PEER_LINK_INFO = 7,
|
||||
ICCP_DBG_CNTR_MSG_HEART_BEAT = 8,
|
||||
ICCP_DBG_CNTR_MSG_NAK = 9,
|
||||
ICCP_DBG_CNTR_MSG_SYNC_DATA = 10,
|
||||
ICCP_DBG_CNTR_MSG_SYNC_REQ = 11,
|
||||
ICCP_DBG_CNTR_MSG_WARM_BOOT = 12,
|
||||
ICCP_DBG_CNTR_MSG_IF_UP_ACK = 13,
|
||||
ICCP_DBG_CNTR_MSG_STP_CONNECT = 14,
|
||||
ICCP_DBG_CNTR_MSG_STP_DISCONNECT = 15,
|
||||
ICCP_DBG_CNTR_MSG_STP_SYSTEM_CONFIG = 16,
|
||||
ICCP_DBG_CNTR_MSG_STP_REGION_NAME = 17,
|
||||
ICCP_DBG_CNTR_MSG_STP_REVISION_LEVEL = 18,
|
||||
ICCP_DBG_CNTR_MSG_STP_INSTANCE_PRIORITY = 19,
|
||||
ICCP_DBG_CNTR_MSG_STP_CONFIGURATION_DIGEST = 20,
|
||||
ICCP_DBG_CNTR_MSG_STP_TC_INSTANCES = 21,
|
||||
ICCP_DBG_CNTR_MSG_STP_ROOT_TIME_PARAM = 22,
|
||||
ICCP_DBG_CNTR_MSG_STP_MIST_ROOT_TIME_PARAM = 23,
|
||||
ICCP_DBG_CNTR_MSG_STP_SYNC_REQ = 24,
|
||||
ICCP_DBG_CNTR_MSG_STP_SYNC_DATA = 25,
|
||||
ICCP_DBG_CNTR_MSG_STP_PO_PORT_MAP = 26,
|
||||
ICCP_DBG_CNTR_MSG_STP_AGE_OUT = 27,
|
||||
ICCP_DBG_CNTR_MSG_STP_COMMON_MSG = 28,
|
||||
ICCP_DBG_CNTR_MSG_MAX
|
||||
};
|
||||
typedef enum ICCP_DBG_CNTR_MSG ICCP_DBG_CNTR_MSG_e;
|
||||
|
||||
/* Count messages sent to MCLAG peer */
|
||||
#define MLACP_SET_ICCP_TX_DBG_COUNTER(csm, tlv_type, status)\
|
||||
do{\
|
||||
ICCP_DBG_CNTR_MSG_e dbg_type;\
|
||||
dbg_type = mlacp_fsm_iccp_to_dbg_msg_type(tlv_type);\
|
||||
if (csm && ((dbg_type) < ICCP_DBG_CNTR_MSG_MAX) && ((status) < ICCP_DBG_CNTR_STS_MAX))\
|
||||
++MLACP(csm).dbg_counters.iccp_counters[dbg_type][ICCP_DBG_CNTR_DIR_TX][status];\
|
||||
}while(0);
|
||||
|
||||
/* Count messages received from MCLAG peer */
|
||||
#define MLACP_SET_ICCP_RX_DBG_COUNTER(csm, tlv_type, status)\
|
||||
do{\
|
||||
ICCP_DBG_CNTR_MSG_e dbg_type;\
|
||||
dbg_type = mlacp_fsm_iccp_to_dbg_msg_type(tlv_type);\
|
||||
if (csm && ((dbg_type) < ICCP_DBG_CNTR_MSG_MAX) && ((status) < ICCP_DBG_CNTR_STS_MAX))\
|
||||
++MLACP(csm).dbg_counters.iccp_counters[dbg_type][ICCP_DBG_CNTR_DIR_RX][status];\
|
||||
}while(0);
|
||||
|
||||
typedef struct mlacp_dbg_counter_info
|
||||
{
|
||||
uint64_t iccp_counters[ICCP_DBG_CNTR_MSG_MAX][ICCP_DBG_CNTR_DIR_MAX][ICCP_DBG_CNTR_STS_MAX];
|
||||
}mlacp_dbg_counter_info_t;
|
||||
|
||||
struct mLACP
|
||||
{
|
||||
int id;
|
||||
@ -88,12 +170,16 @@ struct mLACP
|
||||
TAILQ_HEAD(arp_info_list, Msg) arp_list;
|
||||
TAILQ_HEAD(ndisc_msg_list, Msg) ndisc_msg_list;
|
||||
TAILQ_HEAD(ndisc_info_list, Msg) ndisc_list;
|
||||
TAILQ_HEAD(mac_msg_list, Msg) mac_msg_list;
|
||||
TAILQ_HEAD(mac_info_list, Msg) mac_list;
|
||||
TAILQ_HEAD(mac_msg_list, MACMsg) mac_msg_list;
|
||||
|
||||
struct mac_rb_tree mac_rb;
|
||||
|
||||
LIST_HEAD(lif_list, LocalInterface) lif_list;
|
||||
LIST_HEAD(lif_purge_list, LocalInterface) lif_purge_list;
|
||||
LIST_HEAD(pif_list, PeerInterface) pif_list;
|
||||
|
||||
/* ICCP message tx/rx debug counters */
|
||||
mlacp_dbg_counter_info_t dbg_counters;
|
||||
};
|
||||
|
||||
void mlacp_init(struct CSM* csm, int all);
|
||||
@ -101,9 +187,13 @@ void mlacp_finalize(struct CSM* csm);
|
||||
void mlacp_fsm_transit(struct CSM* csm);
|
||||
void mlacp_enqueue_msg(struct CSM*, struct Msg*);
|
||||
struct Msg* mlacp_dequeue_msg(struct CSM*);
|
||||
char* mlacp_state(struct CSM* csm);
|
||||
|
||||
/* from app_csm*/
|
||||
extern int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* local_if);
|
||||
extern int mlacp_unbind_local_if(struct LocalInterface* local_if);
|
||||
|
||||
/* Debug counter API */
|
||||
ICCP_DBG_CNTR_MSG_e mlacp_fsm_iccp_to_dbg_msg_type(uint32_t tlv_type);
|
||||
|
||||
#endif /* _MLACP_HANDLER_H */
|
||||
|
@ -23,9 +23,16 @@
|
||||
#ifndef __MLACP_LINK_HANDLER__
|
||||
#define __MLACP_LINK_HANDLER__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../include/iccp_csm.h"
|
||||
#include "../include/mlacp_tlv.h"
|
||||
|
||||
#define MCLAG_MAX_MSG_LEN 4096
|
||||
#define ICCP_MLAGSYNCD_SEND_MSG_BUFFER_SIZE MCLAG_MAX_MSG_LEN
|
||||
#define ICCP_MLAGSYNCD_RECV_MSG_BUFFER_SIZE (MCLAG_MAX_MSG_LEN * 256)
|
||||
|
||||
extern char g_iccp_recv_buf[];
|
||||
|
||||
/*****************************************
|
||||
* Link Handler
|
||||
*
|
||||
@ -43,18 +50,48 @@ void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable);
|
||||
void peerlink_port_isolate_cleanup(struct CSM* csm);
|
||||
void update_peerlink_isolate_from_all_csm_lif(struct CSM* csm);
|
||||
|
||||
void del_mac_from_chip(struct MACMsg *mac_msg);
|
||||
void add_mac_to_chip(struct MACMsg *mac_msg, uint8_t mac_type);
|
||||
uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg *mac_msg, uint8_t set);
|
||||
void iccp_get_fdb_change_from_syncd(void);
|
||||
ssize_t iccp_send_to_mclagsyncd(uint8_t msg_type, char *send_buff, uint16_t send_len);
|
||||
|
||||
void del_mac_from_chip(struct MACMsg* mac_msg);
|
||||
void add_mac_to_chip(struct MACMsg* mac_msg, uint8_t mac_type);
|
||||
uint8_t set_mac_local_age_flag(struct CSM *csm, struct MACMsg* mac_msg, uint8_t set, uint8_t update_peer);
|
||||
|
||||
extern int mclagd_ctl_sock_create();
|
||||
extern int mclagd_ctl_sock_accept(int fd);
|
||||
extern int mclagd_ctl_interactive_process(int client_fd);
|
||||
extern int parseMacString(const char *str_mac, uint8_t *bin_mac);
|
||||
|
||||
char *show_ip_str(uint32_t ipv4_addr);
|
||||
char *show_ipv6_str(char *ipv6_addr);
|
||||
|
||||
void syncd_info_close();
|
||||
int iccp_connect_syncd();
|
||||
|
||||
void mlacp_link_disable_traffic_distribution(struct LocalInterface *lif);
|
||||
void mlacp_link_enable_traffic_distribution(struct LocalInterface *lif);
|
||||
int mlacp_link_set_iccp_state(int mlag_id, bool is_oper_up);
|
||||
int mlacp_link_set_iccp_role(int mlag_id, bool is_active_role, uint8_t *system_id);
|
||||
int mlacp_link_set_iccp_system_id(int mlag_id, uint8_t *system_id);
|
||||
int mlacp_link_del_iccp_info(int mlag_id);
|
||||
int mlacp_link_set_remote_if_state(int mlag_id, char *po_name, bool is_oper_up);
|
||||
int mlacp_link_del_remote_if_info(int mlag_id, char *po_name);
|
||||
int mlacp_link_set_peerlink_port_isolation(int mlag_id, char *po_name, bool is_isolation_enable);
|
||||
|
||||
void mlacp_mlag_intf_detach_handler(struct CSM* csm, struct LocalInterface* local_if);
|
||||
void mlacp_peer_mlag_intf_delete_handler(struct CSM* csm, char *mlag_if_name);
|
||||
|
||||
int iccp_mclagsyncd_msg_handler(struct System *sys);
|
||||
int syn_local_neigh_mac_info_to_peer(struct LocalInterface *local_if, int sync_add,
|
||||
int is_v4, int is_v6, int sync_mac, int ack, int is_ipv6_ll, int dir);
|
||||
int syn_local_mac_info_to_peer(struct CSM* csm, struct LocalInterface *local_if, int sync_add, int is_sag);
|
||||
int syn_local_arp_info_to_peer(struct CSM* csm, struct LocalInterface *local_if, int sync_add, int ack);
|
||||
int syn_local_nd_info_to_peer(struct CSM* csm, struct LocalInterface *local_if, int sync_add, int ack, int is_ipv6_ll, int dir);
|
||||
int syn_ack_local_neigh_mac_info_to_peer(char *ifname, int is_ipv6_ll);
|
||||
int is_unique_ip_configured(char *ifname);
|
||||
void set_peerlink_learn_kernel(struct CSM* csm, int enable, int dir);
|
||||
void set_peer_mac_in_kernel(char *mac, int vlan, int add);
|
||||
void mlacp_fix_bridge_mac(struct CSM* csm);
|
||||
void update_orphan_port_mac(struct CSM *csm, struct LocalInterface *lif, int state);
|
||||
void mlacp_convert_remote_mac_to_local(struct CSM *csm, char *po_name);
|
||||
int sync_unique_ip();
|
||||
#endif
|
||||
|
@ -45,12 +45,19 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu
|
||||
int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_size, int end);
|
||||
int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size);
|
||||
int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_buf_size, struct MACMsg* mac_msg, int count);
|
||||
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count);
|
||||
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count);
|
||||
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count, int dir);
|
||||
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count, int dir);
|
||||
int mlacp_prepare_for_heartbeat(struct CSM* csm, char* buf, size_t max_buf_size);
|
||||
int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* local_if);
|
||||
int mlacp_prepare_for_Aggport_config(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* lif, int purge_flag);
|
||||
int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* port_channel);
|
||||
int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf, size_t max_buf_size, struct LocalInterface* peerlink_port);
|
||||
int iccp_netlink_if_hwaddr_set(uint32_t ifindex, uint8_t *addr, unsigned int addr_len);
|
||||
#endif
|
||||
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
|
||||
|
@ -36,15 +36,16 @@ 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_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_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv);
|
||||
|
||||
void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg);
|
||||
void mlacp_enqueue_ndisc(struct CSM *csm, struct Msg* msg);
|
||||
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_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_mac_info_from_peer(struct CSM* csm, struct mLACPMACInfoTLV* tlv);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -28,6 +28,9 @@
|
||||
|
||||
#include "../include/msg_format.h"
|
||||
#include "../include/port.h"
|
||||
#include "../include/openbsd_tree.h"
|
||||
#include "../include/mlacp_tlv.h"
|
||||
|
||||
|
||||
#define MLACP_SYSCONF_NODEID_MSB_MASK 0x80
|
||||
#define MLACP_SYSCONF_NODEID_NODEID_MASK 0x70
|
||||
@ -349,8 +352,9 @@ struct mLACPVLANInfoTLV
|
||||
/* Mac entry Information TLV*/
|
||||
struct mLACPMACData
|
||||
{
|
||||
uint8_t type;/*add or del*/
|
||||
char mac_str[ETHER_ADDR_STR_LEN];
|
||||
uint8_t type;/*add or del*/
|
||||
uint8_t mac_type;
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
uint16_t vid;
|
||||
/*Current if name that set in chip*/
|
||||
char ifname[MAX_L_PORT_NAME];
|
||||
@ -366,17 +370,24 @@ struct mLACPMACInfoTLV
|
||||
struct mLACPMACData MacEntry[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define NEIGH_LOCAL 1
|
||||
#define NEIGH_REMOTE 2
|
||||
|
||||
struct ARPMsg
|
||||
{
|
||||
uint8_t op_type;
|
||||
char ifname[MAX_L_PORT_NAME];
|
||||
uint32_t ipv4_addr;
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
uint8_t op_type;
|
||||
uint8_t flag;
|
||||
uint8_t learn_flag; /*Loacl or Remote*/
|
||||
char ifname[MAX_L_PORT_NAME];
|
||||
uint32_t ipv4_addr; // net order
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
struct NDISCMsg
|
||||
{
|
||||
uint8_t op_type;
|
||||
uint8_t flag;
|
||||
uint8_t learn_flag; /*Loacl or Remote*/
|
||||
char ifname[MAX_L_PORT_NAME];
|
||||
uint32_t ipv6_addr[4];
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
@ -387,7 +398,7 @@ struct NDISCMsg
|
||||
*/
|
||||
struct mLACPARPInfoTLV
|
||||
{
|
||||
ICCParameter icc_parameter;
|
||||
ICCParameter icc_parameter;
|
||||
/* Local Interface ID */
|
||||
uint16_t num_of_entry;
|
||||
struct ARPMsg ArpEntry[0];
|
||||
@ -432,11 +443,50 @@ struct mLACPWarmbootTLV
|
||||
uint8_t warmboot;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* NOS: interface up ack message
|
||||
* ACK is sent by MLAG peer after processing MLAG interface up notification.
|
||||
* The ack indicates that port-isolation is applied on the MLAG peer node
|
||||
*/
|
||||
typedef uint8_t PORT_ISOLATION_STATE_e;
|
||||
enum PORT_ISOLATION_STATE_e
|
||||
{
|
||||
PORT_ISOLATION_STATE_DISABLE = 0,
|
||||
PORT_ISOLATION_STATE_ENABLE = 1
|
||||
};
|
||||
|
||||
typedef uint8_t IF_UP_ACK_TYPE_e;
|
||||
enum IF_UP_ACK_TYPE_e
|
||||
{
|
||||
IF_UP_ACK_TYPE_PHY_PORT = 0,
|
||||
IF_UP_ACK_TYPE_PORT_CHANNEL = 1
|
||||
};
|
||||
|
||||
struct mLACPIfUpAckTLV {
|
||||
ICCParameter icc_parameter;
|
||||
uint8_t if_type;
|
||||
uint8_t port_isolation_state;
|
||||
uint16_t if_id; /* LAG: agg_id */
|
||||
}__attribute__ ((packed));
|
||||
|
||||
enum NEIGH_OP_TYPE
|
||||
{
|
||||
NEIGH_SYNC_LIF,
|
||||
NEIGH_SYNC_ADD,
|
||||
NEIGH_SYNC_DEL,
|
||||
NEIGH_SYNC_LIF = 0,
|
||||
NEIGH_SYNC_ADD = 1,
|
||||
NEIGH_SYNC_DEL = 2,
|
||||
};
|
||||
|
||||
enum NEIGH_FLAG
|
||||
{
|
||||
NEIGH_SYNC_FLAG_ACK = 1,
|
||||
NEIGH_SYNC_FLAG_SELF_LL = 2,
|
||||
NEIGH_SYNC_FLAG_SELF_IP = 4,
|
||||
};
|
||||
|
||||
enum NEIGH_SYNC_DIR
|
||||
{
|
||||
NEIGH_SYNC_CLIENT_IP = 1,
|
||||
NEIGH_SYNC_SELF_IP = 2,
|
||||
};
|
||||
|
||||
enum MAC_AGE_TYPE
|
||||
@ -456,20 +506,30 @@ enum MAC_TYPE
|
||||
{
|
||||
MAC_TYPE_STATIC = 1,
|
||||
MAC_TYPE_DYNAMIC = 2,
|
||||
MAC_TYPE_DYNAMIC_LOCAL = 3, /* Used while sending MAC to Syncd to program with aging enabled. */
|
||||
};
|
||||
|
||||
struct MACMsg
|
||||
{
|
||||
RB_ENTRY(MACMsg) mac_entry_rb;
|
||||
uint16_t vid;
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
uint8_t op_type; /*add or del*/
|
||||
uint8_t fdb_type; /*static or dynamic*/
|
||||
char mac_str[ETHER_ADDR_STR_LEN];
|
||||
uint16_t vid;
|
||||
|
||||
/*Current if name that set in chip*/
|
||||
char ifname[MAX_L_PORT_NAME];
|
||||
/*if we set the mac to peer-link, origin_ifname store the
|
||||
original if name that learned from chip*/
|
||||
char origin_ifname[MAX_L_PORT_NAME];
|
||||
uint8_t age_flag;/*local or peer is age?*/
|
||||
uint8_t pending_local_del;
|
||||
uint8_t add_to_syncd;
|
||||
|
||||
TAILQ_ENTRY(MACMsg) tail; // entry into mac_msg_list
|
||||
};
|
||||
|
||||
RB_HEAD(mac_rb_tree, MACMsg);
|
||||
RB_PROTOTYPE(mac_rb_tree, MACMsg, mac_entry_rb, MACMsg_compare);
|
||||
|
||||
#endif /* MLACP_TLV_H_ */
|
||||
|
@ -29,6 +29,11 @@
|
||||
|
||||
#define MAX_MSG_LOG_SIZE 128
|
||||
|
||||
#define ETHER_ADDR_LEN 6
|
||||
|
||||
/* Header version for message sent from ICCPd to Mclagsyncd */
|
||||
#define ICCPD_TO_MCLAGSYNCD_HDR_VERSION 1
|
||||
|
||||
/*
|
||||
* RFC 5561
|
||||
* 4. Capability Message
|
||||
@ -99,7 +104,8 @@
|
||||
#define TLV_T_MLACP_MAC_INFO 0x1038
|
||||
#define TLV_T_MLACP_WARMBOOT_FLAG 0x1039
|
||||
#define TLV_T_MLACP_NDISC_INFO 0x103A
|
||||
#define TLV_T_MLACP_LIST_END 0x104a // list end
|
||||
#define TLV_T_MLACP_IF_UP_ACK 0x103B
|
||||
#define TLV_T_MLACP_LIST_END 0x104a //list end
|
||||
|
||||
/* Debug */
|
||||
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:
|
||||
return "TLV_T_MLACP_STP_INFO";
|
||||
|
||||
case TLV_T_MLACP_IF_UP_ACK:
|
||||
return "TLV_T_MLACP_IF_UP_ACK";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
@ -426,8 +435,12 @@ struct AppDisconnectCauseTLV
|
||||
/*syncd send msg type to iccpd*/
|
||||
typedef enum mclag_syncd_msg_type_e_
|
||||
{
|
||||
MCLAG_SYNCD_MSG_TYPE_NONE = 0,
|
||||
MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1
|
||||
MCLAG_SYNCD_MSG_TYPE_NONE = 0,
|
||||
MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1,
|
||||
MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN = 2,
|
||||
MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE = 3,
|
||||
MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES = 4,
|
||||
MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP = 5
|
||||
}mclag_syncd_msg_type_e;
|
||||
|
||||
typedef enum mclag_msg_type_e_
|
||||
@ -438,7 +451,16 @@ typedef enum mclag_msg_type_e_
|
||||
MCLAG_MSG_TYPE_FLUSH_FDB = 3,
|
||||
MCLAG_MSG_TYPE_SET_MAC = 4,
|
||||
MCLAG_MSG_TYPE_SET_FDB = 5,
|
||||
MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20
|
||||
MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_ENABLE = 6,
|
||||
MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE = 7,
|
||||
MCLAG_MSG_TYPE_SET_ICCP_STATE = 8,
|
||||
MCLAG_MSG_TYPE_SET_ICCP_ROLE = 9,
|
||||
MCLAG_MSG_TYPE_SET_ICCP_SYSTEM_ID = 10,
|
||||
MCLAG_MSG_TYPE_DEL_ICCP_INFO = 11,
|
||||
MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE = 12,
|
||||
MCLAG_MSG_TYPE_DEL_REMOTE_IF_INFO = 13,
|
||||
MCLAG_MSG_TYPE_SET_PEER_LINK_ISOLATION = 14,
|
||||
MCLAG_MSG_TYPE_SET_ICCP_PEER_SYSTEM_ID = 15
|
||||
}mclag_msg_type_e;
|
||||
|
||||
|
||||
@ -450,9 +472,33 @@ typedef enum mclag_sub_option_type_e_
|
||||
MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3,
|
||||
MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4,
|
||||
MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5,
|
||||
MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6
|
||||
MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6,
|
||||
MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME = 7,
|
||||
MCLAG_SUB_OPTION_TYPE_MCLAG_ID = 8,
|
||||
MCLAG_SUB_OPTION_TYPE_ICCP_ROLE = 9,
|
||||
MCLAG_SUB_OPTION_TYPE_SYSTEM_ID = 10,
|
||||
MCLAG_SUB_OPTION_TYPE_OPER_STATUS = 11,
|
||||
MCLAG_SUB_OPTION_TYPE_ISOLATION_STATE = 12,
|
||||
MCLAG_SUB_OPTION_TYPE_PEER_SYSTEM_ID = 13
|
||||
} mclag_sub_option_type_e;
|
||||
|
||||
enum MCLAG_DOMAIN_CFG_OP_TYPE {
|
||||
MCLAG_CFG_OPER_NONE = 0, //NOP
|
||||
MCLAG_CFG_OPER_ADD = 1, //Add domain
|
||||
MCLAG_CFG_OPER_DEL = 2, //Delete domain
|
||||
MCLAG_CFG_OPER_UPDATE = 3, //update domain
|
||||
MCLAG_CFG_OPER_ATTR_DEL = 4 //Attribute del
|
||||
};
|
||||
|
||||
|
||||
enum MCLAG_DOMAIN_CFG_ATTR_BMAP_FLAGS {
|
||||
MCLAG_CFG_ATTR_NONE = 0x0,
|
||||
MCLAG_CFG_ATTR_SRC_ADDR = 0x1,
|
||||
MCLAG_CFG_ATTR_PEER_ADDR = 0x2,
|
||||
MCLAG_CFG_ATTR_PEER_LINK = 0x4,
|
||||
MCLAG_CFG_ATTR_KEEPALIVE_INTERVAL = 0x8,
|
||||
MCLAG_CFG_ATTR_SESSION_TIMEOUT = 0x10
|
||||
};
|
||||
|
||||
struct IccpSyncdHDr
|
||||
{
|
||||
@ -475,11 +521,37 @@ typedef struct mclag_sub_option_hdr_t_
|
||||
|
||||
struct mclag_fdb_info
|
||||
{
|
||||
char mac[ETHER_ADDR_STR_LEN];
|
||||
uint8_t mac[ETHER_ADDR_LEN];
|
||||
unsigned int vid;
|
||||
char port_name[MAX_L_PORT_NAME];
|
||||
short type; /*dynamic or static*/
|
||||
short op_type; /*add or del*/
|
||||
short type; /*dynamic or static*/
|
||||
short op_type; /*add or del*/
|
||||
};
|
||||
|
||||
struct mclag_domain_cfg_info
|
||||
{
|
||||
int op_type;/*add/del domain; add/del mclag domain */
|
||||
int domain_id;
|
||||
int keepalive_time;
|
||||
int session_timeout;
|
||||
char local_ip[INET_ADDRSTRLEN];
|
||||
char peer_ip[INET_ADDRSTRLEN];
|
||||
char peer_ifname[MAX_L_PORT_NAME];
|
||||
uint8_t system_mac[ETHER_ADDR_LEN];
|
||||
int attr_bmap;
|
||||
};
|
||||
|
||||
struct mclag_iface_cfg_info
|
||||
{
|
||||
int op_type; /*add/del mclag iface */
|
||||
int domain_id;
|
||||
char mclag_iface[MAX_L_PORT_NAME];
|
||||
};
|
||||
|
||||
struct mclag_unique_ip_cfg_info
|
||||
{
|
||||
int op_type;/*add/del mclag unique ip iface */
|
||||
char mclag_unique_ip_ifname[MAX_L_PORT_NAME];
|
||||
};
|
||||
|
||||
/* For storing message log: For Notification TLV */
|
||||
@ -491,6 +563,13 @@ struct MsgTypeSet
|
||||
|
||||
};
|
||||
|
||||
struct mclag_vlan_mbr_info
|
||||
{
|
||||
int op_type;/*add/del vlan_member */
|
||||
unsigned int vid;
|
||||
char mclag_iface[MAX_L_PORT_NAME];
|
||||
};
|
||||
|
||||
struct MsgLog
|
||||
{
|
||||
struct MsgTypeSet msg[MAX_MSG_LOG_SIZE];
|
||||
|
571
src/iccpd/include/openbsd_tree.h
Normal file
571
src/iccpd/include/openbsd_tree.h
Normal 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_ */
|
@ -25,9 +25,17 @@
|
||||
#define PORT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include "../include/openbsd_tree.h"
|
||||
|
||||
#ifndef INET_ADDRSTRLEN
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#endif /* INET_ADDRSTRLEN */
|
||||
|
||||
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#define ETHER_ADDR_STR_LEN 18
|
||||
/*
|
||||
@ -47,9 +55,10 @@
|
||||
#define IF_T_UNKNOW -1
|
||||
#define IF_T_PORT 0
|
||||
#define IF_T_PORT_CHANNEL 1
|
||||
#define IF_T_VLAN 2
|
||||
#define IF_T_VXLAN 3
|
||||
#define IF_T_BRIDGE 4
|
||||
#define IF_T_VLAN 2
|
||||
#define IF_T_VXLAN 3
|
||||
#define IF_T_BRIDGE 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *ifname;
|
||||
@ -62,14 +71,38 @@ struct If_info
|
||||
LIST_ENTRY(If_info) csm_next;
|
||||
};
|
||||
|
||||
struct Unq_ip_If_info
|
||||
{
|
||||
char name[MAX_L_PORT_NAME];
|
||||
LIST_ENTRY(Unq_ip_If_info) if_next;
|
||||
};
|
||||
|
||||
struct VLAN_ID
|
||||
{
|
||||
uint16_t vid;
|
||||
uint16_t vlan_removed;
|
||||
struct LocalInterface* vlan_itf; /* loacl vlan interface */
|
||||
LIST_ENTRY(VLAN_ID) port_next;
|
||||
RB_ENTRY(VLAN_ID) vlan_entry;
|
||||
};
|
||||
|
||||
RB_HEAD(vlan_rb_tree, VLAN_ID);
|
||||
RB_PROTOTYPE(vlan_rb_tree, VLAN_ID, vlan_rb_tree, vlan_node_compare);
|
||||
|
||||
struct PendingVlanMbrIf
|
||||
{
|
||||
char name[MAX_L_PORT_NAME];
|
||||
struct vlan_rb_tree vlan_tree;
|
||||
LIST_ENTRY(PendingVlanMbrIf) if_next;
|
||||
};
|
||||
|
||||
#define VLAN_RB_REMOVE(name, head, elm) do { \
|
||||
RB_REMOVE(name, head, elm); \
|
||||
(elm)->vlan_entry.rbt_parent = NULL; \
|
||||
(elm)->vlan_entry.rbt_left = NULL; \
|
||||
(elm)->vlan_entry.rbt_right = NULL; \
|
||||
} while (0)
|
||||
|
||||
|
||||
struct PeerInterface
|
||||
{
|
||||
int ifindex;
|
||||
@ -88,7 +121,7 @@ struct PeerInterface
|
||||
struct CSM* csm;
|
||||
|
||||
LIST_ENTRY(PeerInterface) mlacp_next;
|
||||
LIST_HEAD(peer_vlan_list, VLAN_ID) vlan_list;
|
||||
struct vlan_rb_tree vlan_tree;
|
||||
};
|
||||
|
||||
struct LocalInterface
|
||||
@ -104,6 +137,8 @@ struct LocalInterface
|
||||
uint8_t prefixlen;
|
||||
uint32_t ipv6_addr[4];
|
||||
uint8_t prefixlen_v6;
|
||||
uint32_t ipv6_ll_addr[4];
|
||||
uint8_t ll_prefixlen_v6;
|
||||
|
||||
uint8_t l3_mode;
|
||||
uint8_t l3_mac_addr[ETHER_ADDR_LEN];
|
||||
@ -115,12 +150,18 @@ struct LocalInterface
|
||||
int mlacp_state; /* Record mlacp state */
|
||||
uint8_t isolate_to_peer_link;
|
||||
|
||||
time_t po_down_time;
|
||||
|
||||
struct CSM* csm;
|
||||
|
||||
uint8_t changed;
|
||||
uint8_t port_config_sync;
|
||||
bool is_traffic_disable; /* Disable traffic tx/rx */
|
||||
bool is_l3_proto_enabled; /* Enable L3 Protocol support */
|
||||
uint32_t vlan_count;
|
||||
uint32_t master_ifindex; /* VRF ifindex*/
|
||||
|
||||
LIST_HEAD(local_vlan_list, VLAN_ID) vlan_list;
|
||||
struct vlan_rb_tree vlan_tree;
|
||||
|
||||
LIST_ENTRY(LocalInterface) system_next;
|
||||
LIST_ENTRY(LocalInterface) system_purge_next;
|
||||
@ -128,7 +169,7 @@ struct LocalInterface
|
||||
LIST_ENTRY(LocalInterface) mlacp_purge_next;
|
||||
};
|
||||
|
||||
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type);
|
||||
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type, uint8_t state);
|
||||
struct LocalInterface* local_if_find_by_name(const char* ifname);
|
||||
struct LocalInterface* local_if_find_by_ifindex(int ifindex);
|
||||
struct LocalInterface* local_if_find_by_po_id(int po_id);
|
||||
@ -141,7 +182,6 @@ int local_if_is_l3_mode(struct LocalInterface* local_if);
|
||||
void local_if_init(struct LocalInterface*);
|
||||
void local_if_finalize(struct LocalInterface*);
|
||||
|
||||
void ether_mac_set_addr_with_if_name(char *name, uint8_t* mac);
|
||||
struct PeerInterface* peer_if_create(struct CSM* csm, int peer_if_number, int type);
|
||||
struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name);
|
||||
|
||||
|
@ -38,9 +38,9 @@ struct CSM;
|
||||
struct System;
|
||||
|
||||
#define CONNECT_INTERVAL_SEC 1
|
||||
#define CONNECT_TIMEOUT_MSEC 100
|
||||
#define CONNECT_TIMEOUT_MSEC 100
|
||||
#define HEARTBEAT_TIMEOUT_SEC 15
|
||||
#define TRANSIT_INTERVAL_SEC 1
|
||||
#define TRANSIT_INTERVAL_SEC 1
|
||||
#define EPOLL_TIMEOUT_MSEC 100
|
||||
|
||||
int scheduler_prepare_session(struct CSM*);
|
||||
@ -56,5 +56,6 @@ int scheduler_csm_read_callback(struct CSM* csm);
|
||||
int iccp_get_server_sock_fd();
|
||||
int scheduler_server_accept();
|
||||
int iccp_receive_signal_handler(struct System* sys);
|
||||
void scheduler_csm_socket_cleanup(struct CSM* csm, int location);
|
||||
|
||||
#endif /* SCHEDULER_H_ */
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#include "../include/port.h"
|
||||
|
||||
@ -52,6 +53,245 @@ struct CSM;
|
||||
#define MAX_BUFSIZE 4096
|
||||
#endif
|
||||
|
||||
extern char mac_print_str[ETHER_ADDR_STR_LEN];
|
||||
|
||||
#define MAC_IN_MSG_LIST(head, elm, field) \
|
||||
(((elm)->field.tqe_next != NULL) || \
|
||||
((elm)->field.tqe_prev != NULL))
|
||||
|
||||
#define CLEAR_MAC_IN_MSG_LIST(head, elm, field) \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = NULL;
|
||||
|
||||
#define MAC_TAILQ_REMOVE(head, elm, field) do { \
|
||||
TAILQ_REMOVE(head, elm, field); \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define MAC_RB_REMOVE(name, head, elm) do { \
|
||||
RB_REMOVE(name, head, elm); \
|
||||
(elm)->mac_entry_rb.rbt_parent = NULL; \
|
||||
(elm)->mac_entry_rb.rbt_left = NULL; \
|
||||
(elm)->mac_entry_rb.rbt_right = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
/* Debug counters */
|
||||
/* Debug counters to track messages ICCPd sent to MclagSyncd */
|
||||
typedef uint8_t SYNCD_DBG_CNTR_STS_e;
|
||||
enum SYNCD_DBG_CNTR_STS_e
|
||||
{
|
||||
SYNCD_DBG_CNTR_STS_OK = 0,
|
||||
SYNCD_DBG_CNTR_STS_ERR = 1, /* Send error or receive processing error*/
|
||||
SYNCD_DBG_CNTR_STS_MAX
|
||||
};
|
||||
|
||||
typedef uint8_t SYNCD_TX_DBG_CNTR_MSG_e;
|
||||
enum SYNCD_TX_DBG_CNTR_MSG_e
|
||||
{
|
||||
SYNCD_TX_DBG_CNTR_MSG_PORT_ISOLATE = 0,
|
||||
SYNCD_TX_DBG_CNTR_MSG_PORT_MAC_LEARN_MODE = 1,
|
||||
SYNCD_TX_DBG_CNTR_MSG_FLUSH_FDB = 2,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_IF_MAC = 3,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_FDB = 4,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_ENABLE = 5,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_DISABLE = 6,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_STATE = 7,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_ROLE = 8,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_SYSTEM_ID = 9,
|
||||
SYNCD_TX_DBG_CNTR_MSG_DEL_ICCP_INFO = 10,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_REMOTE_IF_STATE = 11,
|
||||
SYNCD_TX_DBG_CNTR_MSG_DEL_REMOTE_IF_INFO = 12,
|
||||
SYNCD_TX_DBG_CNTR_MSG_PEER_LINK_ISOLATION = 13,
|
||||
SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_PEER_SYSTEM_ID = 14,
|
||||
SYNCD_TX_DBG_CNTR_MSG_MAX
|
||||
};
|
||||
|
||||
typedef uint8_t SYNCD_RX_DBG_CNTR_MSG_e;
|
||||
enum SYNCD_RX_DBG_CNTR_MSG_e
|
||||
{
|
||||
SYNCD_RX_DBG_CNTR_MSG_MAC = 0,
|
||||
SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_DOMAIN = 1,
|
||||
SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_IFACE = 2,
|
||||
SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_UNIQUE_IP = 3,
|
||||
SYNCD_RX_DBG_CNTR_MSG_VLAN_MBR_UPDATES = 4,
|
||||
SYNCD_RX_DBG_CNTR_MSG_MAX
|
||||
};
|
||||
|
||||
/* Count messages ICCP daemon sent to MclagSyncd */
|
||||
#define SYSTEM_SET_SYNCD_TX_DBG_COUNTER(sys, syncd_msg_type, status)\
|
||||
do{\
|
||||
SYNCD_TX_DBG_CNTR_MSG_e dbg_type;\
|
||||
dbg_type = system_syncdtx_to_dbg_msg_type(syncd_msg_type);\
|
||||
if (sys && ((dbg_type) < SYNCD_TX_DBG_CNTR_MSG_MAX) && ((status) < SYNCD_DBG_CNTR_STS_MAX))\
|
||||
{\
|
||||
++sys->dbg_counters.syncd_tx_counters[dbg_type][status];\
|
||||
}\
|
||||
}while(0);
|
||||
|
||||
/* Count messages ICCP daemon received from MclagSyncd */
|
||||
#define SYSTEM_SET_SYNCD_RX_DBG_COUNTER(sys, syncd_msg_type, status)\
|
||||
do{\
|
||||
SYNCD_RX_DBG_CNTR_MSG_e dbg_type;\
|
||||
dbg_type = system_syncdrx_to_dbg_msg_type(syncd_msg_type);\
|
||||
if (sys && ((dbg_type) < SYNCD_RX_DBG_CNTR_MSG_MAX) && ((status) < SYNCD_DBG_CNTR_STS_MAX))\
|
||||
{\
|
||||
++sys->dbg_counters.syncd_rx_counters[dbg_type][status];\
|
||||
}\
|
||||
}while(0);
|
||||
|
||||
#define SYSTEM_INCR_SESSION_DOWN_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.session_down_counter;\
|
||||
|
||||
#define SYSTEM_GET_SESSION_DOWN_COUNTER(sys)\
|
||||
( (sys) ? (sys)->dbg_counters.session_down_counter: 0)
|
||||
|
||||
#define SYSTEM_INCR_PEER_LINK_DOWN_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.peer_link_down_counter;\
|
||||
|
||||
#define SYSTEM_INCR_WARMBOOT_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.warmboot_counter;
|
||||
|
||||
#define SYSTEM_INCR_INVALID_PEER_MSG_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_peer_invalid_msg_counter;
|
||||
|
||||
#define SYSTEM_GET_INVALID_PEER_MSG_COUNTER(sys)\
|
||||
((sys) ? ((sys)->dbg_counters.rx_peer_invalid_msg_counter) ? 0)
|
||||
|
||||
#define SYSTEM_INCR_RX_READ_SOCK_ZERO_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_read_sock_zero_len_counter;
|
||||
|
||||
#define SYSTEM_INCR_HDR_READ_SOCK_ERR_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_peer_hdr_read_sock_err_counter;
|
||||
|
||||
#define SYSTEM_INCR_HDR_READ_SOCK_ZERO_LEN_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_peer_hdr_read_sock_zero_len_counter;
|
||||
|
||||
#define SYSTEM_INCR_TLV_READ_SOCK_ERR_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_peer_tlv_read_sock_err_counter;
|
||||
|
||||
#define SYSTEM_INCR_TLV_READ_SOCK_ZERO_LEN_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_peer_tlv_read_sock_zero_len_counter;
|
||||
|
||||
#define SYSTEM_INCR_SOCKET_CLOSE_ERR_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.socket_close_err_counter;
|
||||
|
||||
#define SYSTEM_INCR_SOCKET_CLEANUP_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.socket_cleanup_counter;
|
||||
|
||||
#define SYSTEM_INCR_RX_RETRY_FAIL_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_retry_fail_counter;
|
||||
|
||||
#define SYSTEM_INCR_MAC_ENTRY_ALLOC_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.mac_entry_alloc_counter;
|
||||
|
||||
#define SYSTEM_INCR_MAC_ENTRY_FREE_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.mac_entry_free_counter;
|
||||
|
||||
#define SYSTEM_INCR_RX_READ_SOCK_ZERO_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_read_sock_zero_len_counter;
|
||||
|
||||
#define SYSTEM_INCR_RX_READ_SOCK_ERR_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_read_sock_err_counter;
|
||||
|
||||
#define SYSTEM_INCR_RX_READ_STP_SOCK_ZERO_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_read_stp_sock_zero_len_counter;
|
||||
|
||||
#define SYSTEM_INCR_RX_READ_STP_SOCK_ERR_COUNTER(sys)\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_read_stp_sock_err_counter;
|
||||
#define SYSTEM_SET_RETRY_COUNTER(sys, num_retry)\
|
||||
if (sys)\
|
||||
{\
|
||||
sys->dbg_counters.rx_retry_total_counter += num_retry;\
|
||||
if (num_retry > sys->dbg_counters.rx_retry_max_counter)\
|
||||
sys->dbg_counters.rx_retry_max_counter = num_retry;\
|
||||
}
|
||||
|
||||
#define SYSTEM_INCR_NETLINK_UNKNOWN_IF_NAME(ifname)\
|
||||
do {\
|
||||
struct System *sys;\
|
||||
sys = system_get_instance();\
|
||||
if (sys)\
|
||||
{\
|
||||
++sys->dbg_counters.unknown_if_name_count;\
|
||||
if (sys->dbg_counters.unknown_if_name_count < 10)\
|
||||
{\
|
||||
ICCPD_LOG_NOTICE("ICCP_FSM","NETLINK_COUNTER: Unknown if_name %s", ifname);\
|
||||
}\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define SYSTEM_INCR_NETLINK_RX_ERROR()\
|
||||
do {\
|
||||
struct System *sys;\
|
||||
sys = system_get_instance();\
|
||||
if (sys)\
|
||||
++sys->dbg_counters.rx_error_count;\
|
||||
}while(0)
|
||||
|
||||
typedef struct system_dbg_counter_info
|
||||
{
|
||||
/* Netlink message counters */
|
||||
uint32_t newlink_count;
|
||||
uint32_t dellink_count;
|
||||
uint32_t newnbr_count;
|
||||
uint32_t delnbr_count;
|
||||
uint32_t newaddr_count;
|
||||
uint32_t deladdr_count;
|
||||
uint32_t unknown_type_count;
|
||||
uint32_t rx_error_count;
|
||||
|
||||
/* Netlink link sub-message count */
|
||||
uint32_t unknown_if_name_count;
|
||||
|
||||
/* Netlink neighbor sub-message count */
|
||||
uint32_t newmac_count;
|
||||
uint32_t delmac_count;
|
||||
|
||||
uint32_t session_down_counter; //not counting down due to warmboot
|
||||
uint32_t peer_link_down_counter;
|
||||
uint32_t warmboot_counter;
|
||||
uint32_t rx_peer_invalid_msg_counter; //counts partial msgs received as sending end is not sending partial msgs
|
||||
uint32_t rx_peer_hdr_read_sock_err_counter; //counts socket header read errors
|
||||
uint32_t rx_peer_hdr_read_sock_zero_len_counter; //counts socket header read zero length
|
||||
uint32_t rx_peer_tlv_read_sock_err_counter; //counts socket data/tlv read errors
|
||||
uint32_t rx_peer_tlv_read_sock_zero_len_counter; //counts socket data/tlv read zero length
|
||||
uint32_t socket_close_err_counter; //socket close failure
|
||||
uint32_t socket_cleanup_counter; //socket cleanup outside of session down
|
||||
uint32_t rx_retry_max_counter; //max non-blocking RX retry for one message
|
||||
uint32_t rx_retry_total_counter; //total number of non-blocking RX retry
|
||||
uint32_t rx_retry_fail_counter; //total number of non-blocking RX retry failure
|
||||
|
||||
uint32_t rx_read_sock_zero_len_counter; //counts socket header read zero length from sync_fd
|
||||
uint32_t rx_read_sock_err_counter; //counts socket header read zero length from sync_fd
|
||||
uint32_t rx_read_stp_sock_zero_len_counter; //counts socket header read zero length from syncd
|
||||
uint32_t rx_read_stp_sock_err_counter; //counts socket header read zero length from syncd
|
||||
|
||||
uint32_t mac_entry_alloc_counter;
|
||||
uint32_t mac_entry_free_counter;
|
||||
|
||||
uint64_t syncd_tx_counters[SYNCD_TX_DBG_CNTR_MSG_MAX][SYNCD_DBG_CNTR_STS_MAX];
|
||||
uint64_t syncd_rx_counters[SYNCD_RX_DBG_CNTR_MSG_MAX][SYNCD_DBG_CNTR_STS_MAX];
|
||||
}system_dbg_counter_info_t;
|
||||
|
||||
struct System
|
||||
{
|
||||
int server_fd;/* Peer-Link Socket*/
|
||||
@ -78,6 +318,8 @@ struct System
|
||||
LIST_HEAD(csm_list, CSM) csm_list;
|
||||
LIST_HEAD(lif_all_list, LocalInterface) lif_list;
|
||||
LIST_HEAD(lif_purge_all_list, LocalInterface) lif_purge_list;
|
||||
LIST_HEAD(unq_ip_all_if_list, Unq_ip_If_info) unq_ip_if_list;
|
||||
LIST_HEAD(pending_vlan_mbr_if_list, PendingVlanMbrIf) pending_vlan_mbr_if_list;
|
||||
|
||||
/* Settings */
|
||||
char* log_file_path;
|
||||
@ -91,13 +333,23 @@ struct System
|
||||
time_t csm_trans_time;
|
||||
int need_sync_team_again;
|
||||
int need_sync_netlink_again;
|
||||
|
||||
/* ICCDd/MclagSyncd debug counters */
|
||||
system_dbg_counter_info_t dbg_counters;
|
||||
};
|
||||
|
||||
struct CSM* system_create_csm();
|
||||
struct CSM* system_get_csm_by_peer_ip(const char*);
|
||||
struct CSM* system_get_csm_by_peer_ifname(char *ifname);
|
||||
struct CSM* system_get_csm_by_mlacp_id(int id);
|
||||
struct CSM* system_get_first_csm();
|
||||
struct System* system_get_instance();
|
||||
void system_finalize();
|
||||
void system_init(struct System*);
|
||||
SYNCD_TX_DBG_CNTR_MSG_e system_syncdtx_to_dbg_msg_type(uint32_t msg_type);
|
||||
SYNCD_RX_DBG_CNTR_MSG_e system_syncdrx_to_dbg_msg_type(uint32_t msg_type);
|
||||
|
||||
char *mac_addr_to_str(uint8_t mac_addr[ETHER_ADDR_LEN]);
|
||||
void system_update_netlink_counters(uint16_t netlink_msg_type, struct nlmsghdr *nlh);
|
||||
|
||||
#endif /* SYSTEM_H_ */
|
||||
|
@ -17,6 +17,7 @@ iccpd_SOURCES = \
|
||||
mlacp_link_handler.c \
|
||||
mlacp_sync_prepare.c mlacp_sync_update.c\
|
||||
mlacp_fsm.c \
|
||||
iccp_netlink.c
|
||||
iccp_netlink.c \
|
||||
openbsd_tree.c
|
||||
iccpd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON)
|
||||
iccpd_LDADD = -lnl-genl-3 -lnl-route-3 -lnl-3 -lpthread
|
||||
|
@ -239,7 +239,7 @@ int mlacp_bind_local_if(struct CSM* csm, struct LocalInterface* lif)
|
||||
if (lif_po->type == IF_T_PORT_CHANNEL && lif_po->po_id == lif->po_id)
|
||||
{
|
||||
/*if join a po member, may swss restart, reset portchannel ip mac to mclagsyncd*/
|
||||
update_if_ipmac_on_standby(lif_po);
|
||||
update_if_ipmac_on_standby(lif_po, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -52,10 +52,8 @@ int unset_mc_lag_id( struct CSM *csm, uint16_t id)
|
||||
if (!csm)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
/* Mlag-ID, RG-ID, MLACP-ID*/
|
||||
csm->mlag_id = 0;
|
||||
csm->iccp_info.icc_rg_id = 0;
|
||||
csm->app_csm.mlacp.id = 0;
|
||||
/* Remove ICCP info from STATE_DB */
|
||||
mlacp_link_del_iccp_info(csm->mlag_id);
|
||||
|
||||
iccp_csm_finalize(csm);
|
||||
|
||||
@ -73,7 +71,9 @@ int set_peer_link(int mid, const char* ifname)
|
||||
|
||||
len = strlen(ifname);
|
||||
|
||||
if (strncmp(ifname, FRONT_PANEL_PORT_PREFIX, strlen(FRONT_PANEL_PORT_PREFIX)) != 0 && strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0 && strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) != 0)
|
||||
if (strncmp(ifname, FRONT_PANEL_PORT_PREFIX, strlen(FRONT_PANEL_PORT_PREFIX)) != 0
|
||||
&& strncmp(ifname, PORTCHANNEL_PREFIX, strlen(PORTCHANNEL_PREFIX)) != 0
|
||||
&& strncmp(ifname, VXLAN_TUNNEL_PREFIX, strlen(VXLAN_TUNNEL_PREFIX)) != 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Peer-link is %s, must be Ethernet or PortChannel or VTTNL(Vxlan tunnel)", ifname);
|
||||
return MCLAG_ERROR;
|
||||
@ -83,8 +83,11 @@ int set_peer_link(int mid, const char* ifname)
|
||||
if (csm == NULL)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
if (len > IFNAMSIZ)
|
||||
if (len > MAX_L_PORT_NAME)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Peer-link %s, Strlen %d greater than MAX:%d ", ifname, len, MAX_L_PORT_NAME);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
if (strlen(csm->peer_itf_name) > 0)
|
||||
{
|
||||
@ -114,7 +117,7 @@ int set_peer_link(int mid, const char* ifname)
|
||||
csm->mlag_id, ifname);
|
||||
}
|
||||
|
||||
memset(csm->peer_itf_name, 0, IFNAMSIZ);
|
||||
memset(csm->peer_itf_name, 0, MAX_L_PORT_NAME);
|
||||
memcpy(csm->peer_itf_name, ifname, len);
|
||||
|
||||
/* update peer-link link handler*/
|
||||
@ -128,6 +131,8 @@ int set_peer_link(int mid, const char* ifname)
|
||||
|
||||
if (lif->type == IF_T_PORT_CHANNEL)
|
||||
iccp_get_port_member_list(lif);
|
||||
|
||||
set_peerlink_learn_kernel(csm, 0, 4);
|
||||
}
|
||||
|
||||
/*disconnect the link for mac and arp sync up*/
|
||||
@ -147,15 +152,17 @@ int unset_peer_link(int mid)
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
/*must be enabled mac learn*/
|
||||
if (csm->peer_link_if)
|
||||
if (csm->peer_link_if) {
|
||||
set_peerlink_mlag_port_learn(csm->peer_link_if, 1);
|
||||
set_peerlink_learn_kernel(csm, 1, 5);
|
||||
}
|
||||
}
|
||||
|
||||
/* update peer-link link handler*/
|
||||
scheduler_session_disconnect_handler(csm);
|
||||
|
||||
/* clean peer-link*/
|
||||
memset(csm->peer_itf_name, 0, IFNAMSIZ);
|
||||
memset(csm->peer_itf_name, 0, MAX_L_PORT_NAME);
|
||||
if (csm->peer_link_if)
|
||||
{
|
||||
csm->peer_link_if->is_peer_link = 0;
|
||||
@ -282,6 +289,42 @@ int unset_peer_address(int mid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_keepalive_time(int mid, int keepalive_time)
|
||||
{
|
||||
struct CSM* csm = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
csm = system_get_csm_by_mlacp_id(mid);
|
||||
if (csm == NULL)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Set keepalive_time : %d", keepalive_time);
|
||||
|
||||
if (csm->keepalive_time != keepalive_time)
|
||||
{
|
||||
csm->keepalive_time = keepalive_time;
|
||||
//reset heartbeat send time to send keepalive immediately
|
||||
csm->heartbeat_send_time = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_session_timeout(int mid, int session_timeout_val)
|
||||
{
|
||||
struct CSM* csm = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
csm = system_get_csm_by_mlacp_id(mid);
|
||||
if (csm == NULL)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Set session timeout : %d", session_timeout_val);
|
||||
|
||||
csm->session_timeout = session_timeout_val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int iccp_cli_attach_mclag_domain_to_port_channel( int domain, const char* ifname)
|
||||
{
|
||||
struct CSM* csm = NULL;
|
||||
@ -352,17 +395,30 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname)
|
||||
|| lif_po->po_id <= 0
|
||||
|| lif_po->csm == NULL)
|
||||
{
|
||||
if (lif_po)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "CSM already detached for ifname = %s", lif_po->name);
|
||||
}
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
/* find csm*/
|
||||
csm = lif_po->csm;
|
||||
|
||||
if(!csm)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "unexpected condition!!!; lif->csm not found!; Detach mclag from ifname = %s", lif_po->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Detach mclag id = %d from ifname = %s",
|
||||
csm->mlag_id, lif_po->name);
|
||||
|
||||
//if it is standby node change back the mac to its original system mac
|
||||
recover_if_ipmac_on_standby(lif_po, 1);
|
||||
|
||||
/* process link state handler before detaching it.*/
|
||||
mlacp_mlag_link_del_handler(csm, lif_po);
|
||||
mlacp_mlag_intf_detach_handler(csm, lif_po);
|
||||
|
||||
unbind_poid = lif_po->po_id;
|
||||
mlacp_unbind_local_if(lif_po);
|
||||
@ -377,6 +433,7 @@ int iccp_cli_detach_mclag_domain_to_port_channel( const char* ifname)
|
||||
if (strcmp(ifname, cif->name) == 0)
|
||||
LIST_REMOVE(cif, csm_next);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,21 @@ int set_mc_lag_by_id(uint16_t mid)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int unset_mc_lag_by_id(uint16_t mid)
|
||||
{
|
||||
int ret = 0;
|
||||
struct CSM* csm = NULL;
|
||||
|
||||
csm = system_get_csm_by_mlacp_id(mid);
|
||||
if (csm)
|
||||
{
|
||||
ret = unset_mc_lag_id(csm, mid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
#define CONFIG_LINE_LEN 512
|
||||
|
||||
int iccp_config_from_command(char * line)
|
||||
|
@ -20,6 +20,7 @@
|
||||
*
|
||||
* Maintainer: jianjun, grace Li from nephos
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <net/if.h>
|
||||
@ -33,6 +34,8 @@
|
||||
#include "../include/iccp_cmd_show.h"
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
|
||||
extern int local_if_l3_proto_enabled(const char* ifname);
|
||||
|
||||
int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
|
||||
{
|
||||
struct mclagd_state state_info;
|
||||
@ -67,6 +70,11 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
|
||||
else
|
||||
state_info.keepalive = 0;
|
||||
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
state_info.info_sync_done = 1;
|
||||
else
|
||||
state_info.info_sync_done = 0;
|
||||
|
||||
if (mclag_id > 0)
|
||||
{
|
||||
if (csm->mlag_id == mclag_id)
|
||||
@ -93,13 +101,15 @@ int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id)
|
||||
if (peer_link_if)
|
||||
memcpy(state_info.peer_link_mac, peer_link_if->mac_addr, 6);
|
||||
|
||||
state_info.keepalive_time = csm->keepalive_time;
|
||||
state_info.session_timeout = csm->session_timeout;
|
||||
|
||||
logconfig = logger_get_configuration();
|
||||
memcpy(state_info.loglevel, log_level_to_string(logconfig->log_level), strlen( log_level_to_string(logconfig->log_level)));
|
||||
|
||||
state_info.role = csm->role_type;
|
||||
|
||||
str_size = MCLAGDCTL_PORT_MEMBER_BUF_LEN;
|
||||
len = 0;
|
||||
|
||||
LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
@ -177,6 +187,7 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id)
|
||||
iccpd_arp = (struct ARPMsg*)msg->buf;
|
||||
|
||||
mclagd_arp.op_type = iccpd_arp->op_type;
|
||||
mclagd_arp.learn_flag = iccpd_arp->learn_flag;
|
||||
memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname));
|
||||
memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16);
|
||||
memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6);
|
||||
@ -219,7 +230,6 @@ int iccp_ndisc_dump(char * *buf, int *num, int mclag_id)
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
{
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
|
||||
return EXEC_TYPE_NO_EXIST_SYS;
|
||||
}
|
||||
|
||||
@ -243,12 +253,12 @@ int iccp_ndisc_dump(char * *buf, int *num, int mclag_id)
|
||||
iccpd_ndisc = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
mclagd_ndisc.op_type = iccpd_ndisc->op_type;
|
||||
mclagd_ndisc.learn_flag = iccpd_ndisc->learn_flag;
|
||||
memcpy(mclagd_ndisc.ifname, iccpd_ndisc->ifname, strlen(iccpd_ndisc->ifname));
|
||||
memcpy(mclagd_ndisc.ipv6_addr, show_ipv6_str((char *)iccpd_ndisc->ipv6_addr), 46);
|
||||
memcpy(mclagd_ndisc.mac_addr, iccpd_ndisc->mac_addr, 6);
|
||||
|
||||
memcpy(ndisc_buf + MCLAGD_REPLY_INFO_HDR + ndisc_num * sizeof(struct mclagd_ndisc_msg),
|
||||
&mclagd_ndisc, sizeof(struct mclagd_ndisc_msg));
|
||||
memcpy(ndisc_buf + MCLAGD_REPLY_INFO_HDR + ndisc_num * sizeof(struct mclagd_ndisc_msg), &mclagd_ndisc, sizeof(struct mclagd_ndisc_msg));
|
||||
|
||||
ndisc_num++;
|
||||
|
||||
@ -302,14 +312,13 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id)
|
||||
continue;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail)
|
||||
RB_FOREACH (iccpd_mac, mac_rb_tree, &MLACP(csm).mac_rb)
|
||||
{
|
||||
memset(&mclagd_mac, 0, sizeof(struct mclagd_mac_msg));
|
||||
iccpd_mac = (struct MACMsg*)msg->buf;
|
||||
|
||||
mclagd_mac.op_type = iccpd_mac->op_type;
|
||||
mclagd_mac.fdb_type = iccpd_mac->fdb_type;
|
||||
memcpy(mclagd_mac.mac_str, iccpd_mac->mac_str, ETHER_ADDR_STR_LEN);
|
||||
memcpy(mclagd_mac.mac_addr, iccpd_mac->mac_addr, ETHER_ADDR_LEN);
|
||||
mclagd_mac.vid = iccpd_mac->vid;
|
||||
memcpy(mclagd_mac.ifname, iccpd_mac->ifname, strlen(iccpd_mac->ifname));
|
||||
memcpy(mclagd_mac.origin_ifname, iccpd_mac->origin_ifname, strlen(iccpd_mac->origin_ifname));
|
||||
@ -328,7 +337,7 @@ int iccp_mac_dump(char * *buf, int *num, int mclag_id)
|
||||
return EXEC_TYPE_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*buf = mac_buf;
|
||||
*num = mac_num;
|
||||
@ -344,6 +353,7 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
|
||||
struct System *sys = NULL;
|
||||
struct CSM *csm = NULL;
|
||||
struct LocalInterface *lif_po = NULL;
|
||||
struct LocalInterface *lif_peer = NULL;
|
||||
struct mclagd_local_if mclagd_lif;
|
||||
struct VLAN_ID* vlan_id = NULL;
|
||||
char * str_buf = NULL;
|
||||
@ -398,7 +408,7 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
|
||||
else if (lif_po->state == PORT_STATE_TEST)
|
||||
memcpy(mclagd_lif.state, "Test", 4);
|
||||
|
||||
memcpy(mclagd_lif.ipv4_addr, show_ip_str(htonl(lif_po->ipv4_addr)), 16);
|
||||
memcpy(mclagd_lif.ipv4_addr, show_ip_str(lif_po->ipv4_addr), 16);
|
||||
mclagd_lif.prefixlen = lif_po->prefixlen;
|
||||
|
||||
mclagd_lif.l3_mode = local_if_is_l3_mode(lif_po);
|
||||
@ -422,17 +432,47 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
|
||||
memcpy(mclagd_lif.mlacp_state, "ERROR", 5);
|
||||
|
||||
mclagd_lif.isolate_to_peer_link = lif_po->isolate_to_peer_link;
|
||||
mclagd_lif.is_traffic_disable = lif_po->is_traffic_disable;
|
||||
|
||||
str_buf = mclagd_lif.vlanlist;
|
||||
|
||||
len = 0;
|
||||
LIST_FOREACH(vlan_id, &(lif_po->vlan_list), port_next)
|
||||
int prev_vlan_id = 0;
|
||||
int range = 0;
|
||||
int to_be_printed = 0;
|
||||
|
||||
RB_FOREACH (vlan_id, vlan_rb_tree, &(lif_po->vlan_tree))
|
||||
{
|
||||
if (vlan_id != NULL )
|
||||
if (str_size - len < 4)
|
||||
break;
|
||||
if (!prev_vlan_id || vlan_id->vid != prev_vlan_id + 1)
|
||||
{
|
||||
if (str_size - len < 4)
|
||||
break;
|
||||
if (range)
|
||||
{
|
||||
if (str_size - len < (4 + ((range)?8:0)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
len += snprintf(str_buf + len, str_size - len, "- %d ", prev_vlan_id);
|
||||
}
|
||||
len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid);
|
||||
range = 0;
|
||||
to_be_printed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
range = 1;
|
||||
to_be_printed = 1;
|
||||
}
|
||||
prev_vlan_id = vlan_id->vid;
|
||||
}
|
||||
|
||||
if (to_be_printed && (str_size - len > (4 + ((range)?8:0))))
|
||||
{
|
||||
if (prev_vlan_id)
|
||||
{
|
||||
len += snprintf(str_buf + len, str_size - len, "%s%d ", range?"- ":"", prev_vlan_id);
|
||||
range = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,6 +489,116 @@ int iccp_local_if_dump(char * *buf, int *num, int mclag_id)
|
||||
return EXEC_TYPE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (csm->peer_link_if) {
|
||||
|
||||
lif_peer = csm->peer_link_if;
|
||||
|
||||
memset(&mclagd_lif, 0, sizeof(struct mclagd_local_if));
|
||||
|
||||
mclagd_lif.ifindex = lif_peer->ifindex;
|
||||
|
||||
if (lif_peer->type == IF_T_UNKNOW)
|
||||
memcpy(mclagd_lif.type, "Unknown", strlen("unknown"));
|
||||
else if (lif_peer->type == IF_T_PORT)
|
||||
memcpy(mclagd_lif.type, "Ethernet", strlen("Ethernet"));
|
||||
else if (lif_peer->type == IF_T_PORT_CHANNEL)
|
||||
memcpy(mclagd_lif.type, "PortChannel", 11);
|
||||
|
||||
memcpy(mclagd_lif.name, lif_peer->name, MAX_L_PORT_NAME);
|
||||
memcpy(mclagd_lif.mac_addr, lif_peer->mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
if (lif_peer->state == PORT_STATE_UP)
|
||||
memcpy(mclagd_lif.state, "Up", strlen("Up"));
|
||||
else if (lif_peer->state == PORT_STATE_DOWN)
|
||||
memcpy(mclagd_lif.state, "Down", strlen("Down"));
|
||||
else if (lif_peer->state == PORT_STATE_ADMIN_DOWN)
|
||||
memcpy(mclagd_lif.state, "Admin-down", strlen("Admin-down"));
|
||||
else if (lif_peer->state == PORT_STATE_TEST)
|
||||
memcpy(mclagd_lif.state, "Test", strlen("Test"));
|
||||
|
||||
memcpy(mclagd_lif.ipv4_addr, show_ip_str(lif_peer->ipv4_addr), 16);
|
||||
mclagd_lif.prefixlen = lif_peer->prefixlen;
|
||||
|
||||
mclagd_lif.l3_mode = local_if_is_l3_mode(lif_peer);
|
||||
|
||||
mclagd_lif.is_peer_link = lif_peer->is_peer_link;
|
||||
|
||||
memcpy(mclagd_lif.portchannel_member_buf, lif_peer->portchannel_member_buf, 512);
|
||||
|
||||
mclagd_lif.po_id = lif_peer->po_id;
|
||||
mclagd_lif.po_active = lif_peer->po_active;
|
||||
/*mlacp_state*/
|
||||
if (lif_peer->mlacp_state == MLACP_STATE_INIT)
|
||||
memcpy(mclagd_lif.mlacp_state, "INIT", strlen("INIT"));
|
||||
else if (lif_peer->mlacp_state == MLACP_STATE_STAGE1)
|
||||
memcpy(mclagd_lif.mlacp_state, "STAGE1", strlen("STAGE1"));
|
||||
else if (lif_peer->mlacp_state == MLACP_STATE_STAGE2)
|
||||
memcpy(mclagd_lif.mlacp_state, "STAGE2", strlen("STAGE2"));
|
||||
else if (lif_peer->mlacp_state == MLACP_STATE_EXCHANGE)
|
||||
memcpy(mclagd_lif.mlacp_state, "EXCHANGE", strlen("EXCHANGE"));
|
||||
else if (lif_peer->mlacp_state == MLACP_STATE_ERROR)
|
||||
memcpy(mclagd_lif.mlacp_state, "ERROR", strlen("ERROR"));
|
||||
|
||||
mclagd_lif.isolate_to_peer_link = lif_peer->isolate_to_peer_link;
|
||||
mclagd_lif.is_traffic_disable = lif_peer->is_traffic_disable;
|
||||
|
||||
str_buf = mclagd_lif.vlanlist;
|
||||
|
||||
len = 0;
|
||||
int prev_vlan_id = 0;
|
||||
int range = 0;
|
||||
int to_be_printed = 0;
|
||||
|
||||
RB_FOREACH (vlan_id, vlan_rb_tree, &(lif_peer->vlan_tree))
|
||||
{
|
||||
if (str_size - len < 4)
|
||||
break;
|
||||
if (!prev_vlan_id || vlan_id->vid != prev_vlan_id + 1)
|
||||
{
|
||||
if (range)
|
||||
{
|
||||
if (str_size - len < (4 + ((range)?8:0)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
len += snprintf(str_buf + len, str_size - len, "- %d ", prev_vlan_id);
|
||||
}
|
||||
len += snprintf(str_buf + len, str_size - len, "%d ", vlan_id->vid);
|
||||
range = 0;
|
||||
to_be_printed = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
range = 1;
|
||||
to_be_printed = 1;
|
||||
}
|
||||
prev_vlan_id = vlan_id->vid;
|
||||
}
|
||||
|
||||
if (to_be_printed && (str_size - len > (4 + ((range)?8:0))))
|
||||
{
|
||||
if (prev_vlan_id)
|
||||
{
|
||||
len += snprintf(str_buf + len, str_size - len, "%s%d ", range?"- ":"", prev_vlan_id);
|
||||
range = 0;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num * sizeof(struct mclagd_local_if),
|
||||
&mclagd_lif, sizeof(struct mclagd_local_if));
|
||||
|
||||
lif_num++;
|
||||
|
||||
if ((lif_num + 1) * sizeof(struct mclagd_local_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR))
|
||||
{
|
||||
lif_buf_size += MCLAGDCTL_CMD_SIZE;
|
||||
lif_buf = (char*)realloc(lif_buf, lif_buf_size);
|
||||
if (!lif_buf)
|
||||
return EXEC_TYPE_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
*buf = lif_buf;
|
||||
@ -473,6 +623,7 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id)
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
{
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
|
||||
return EXEC_TYPE_NO_EXIST_SYS;
|
||||
}
|
||||
|
||||
@ -542,3 +693,122 @@ int iccp_peer_if_dump(char * *buf, int *num, int mclag_id)
|
||||
return EXEC_TYPE_SUCCESS;
|
||||
}
|
||||
|
||||
/* Allocate a buffer to return the internal debug counters
|
||||
* The allocated buffer should include MCLAGD_REPLY_INFO_HDR byte header
|
||||
* No buffer is allocated if error is returned
|
||||
*/
|
||||
int iccp_cmd_dbg_counter_dump(char **buf, int *data_len, int mclag_id)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct CSM *csm = NULL;
|
||||
char *temp_ptr, *counter_buf = NULL;
|
||||
mclagd_dbg_counter_info_t *counter_ptr;
|
||||
int buf_size = 0;
|
||||
int id_exist = 0;
|
||||
int num_csm = 0;
|
||||
bool is_first_csm;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
{
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
|
||||
return EXEC_TYPE_NO_EXIST_SYS;
|
||||
}
|
||||
if (mclag_id >0)
|
||||
num_csm = 1;
|
||||
else
|
||||
{
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
++num_csm;
|
||||
}
|
||||
}
|
||||
buf_size = MCLAGD_REPLY_INFO_HDR + sizeof(mclagd_dbg_counter_info_t) +
|
||||
(sizeof(mlacp_dbg_counter_info_t) * num_csm);
|
||||
counter_buf = (char*)malloc(buf_size);
|
||||
if (!counter_buf)
|
||||
return EXEC_TYPE_FAILED;
|
||||
|
||||
memset(counter_buf, 0, buf_size);
|
||||
counter_ptr =
|
||||
(mclagd_dbg_counter_info_t *)(counter_buf + MCLAGD_REPLY_INFO_HDR);
|
||||
memcpy(&counter_ptr->system_dbg, &sys->dbg_counters, sizeof(sys->dbg_counters));
|
||||
counter_ptr->num_iccp_counter_blocks = num_csm;
|
||||
temp_ptr = counter_ptr->iccp_dbg_counters;
|
||||
is_first_csm = true;
|
||||
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
if (mclag_id >0)
|
||||
{
|
||||
if (csm->mlag_id == mclag_id)
|
||||
id_exist = 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
if (is_first_csm)
|
||||
is_first_csm = false;
|
||||
else
|
||||
temp_ptr += sizeof(MLACP(csm).dbg_counters);
|
||||
|
||||
memcpy(temp_ptr, &MLACP(csm).dbg_counters,
|
||||
sizeof(MLACP(csm).dbg_counters));
|
||||
}
|
||||
|
||||
if (mclag_id >0 && !id_exist)
|
||||
{
|
||||
if (counter_buf)
|
||||
free(counter_buf);
|
||||
return EXEC_TYPE_NO_EXIST_MCLAGID;
|
||||
}
|
||||
*buf = counter_buf;
|
||||
*data_len = buf_size - MCLAGD_REPLY_INFO_HDR;
|
||||
return EXEC_TYPE_SUCCESS;
|
||||
}
|
||||
|
||||
int iccp_unique_ip_if_dump(char **buf, int *num, int mclag_id)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct mclagd_unique_ip_if mclagd_lif;
|
||||
char *str_buf = NULL;
|
||||
int str_size = MCLAGDCTL_PARA3_LEN - 1;
|
||||
int len = 0;
|
||||
int lif_num = 0;
|
||||
int lif_buf_size = MCLAGDCTL_CMD_SIZE;
|
||||
char *lif_buf = NULL;
|
||||
struct Unq_ip_If_info* unq_ip_if = NULL;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
{
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
|
||||
return EXEC_TYPE_NO_EXIST_SYS;
|
||||
}
|
||||
|
||||
lif_buf = (char*)malloc(lif_buf_size);
|
||||
if (!lif_buf)
|
||||
return EXEC_TYPE_FAILED;
|
||||
|
||||
LIST_FOREACH(unq_ip_if, &(sys->unq_ip_if_list), if_next)
|
||||
{
|
||||
memset(&mclagd_lif, 0, sizeof(struct mclagd_unique_ip_if));
|
||||
memcpy(mclagd_lif.name, unq_ip_if->name, MAX_L_PORT_NAME);
|
||||
mclagd_lif.active = local_if_l3_proto_enabled(unq_ip_if->name);
|
||||
|
||||
memcpy(lif_buf + MCLAGD_REPLY_INFO_HDR + lif_num * sizeof(struct mclagd_unique_ip_if),
|
||||
&mclagd_lif, sizeof(struct mclagd_unique_ip_if));
|
||||
|
||||
lif_num++;
|
||||
|
||||
if ((lif_num + 1) * sizeof(struct mclagd_unique_ip_if) > (lif_buf_size - MCLAGD_REPLY_INFO_HDR))
|
||||
{
|
||||
lif_buf_size += MCLAGDCTL_CMD_SIZE;
|
||||
lif_buf = (char*)realloc(lif_buf, lif_buf_size);
|
||||
if (!lif_buf)
|
||||
return EXEC_TYPE_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
*buf = lif_buf;
|
||||
*num = lif_num;
|
||||
|
||||
return EXEC_TYPE_SUCCESS;
|
||||
}
|
||||
|
@ -112,13 +112,9 @@ static int iccp_check_interface_vlan(char* ifname)
|
||||
if (peer_if == NULL)
|
||||
return -4;
|
||||
|
||||
LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next)
|
||||
RB_FOREACH (local_vlan, vlan_rb_tree, &(local_if->vlan_tree))
|
||||
{
|
||||
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next)
|
||||
{
|
||||
if (peer_vlan->vid == local_vlan->vid)
|
||||
break;
|
||||
}
|
||||
peer_vlan = RB_FIND(vlan_rb_tree, &(peer_if->vlan_tree), local_vlan);
|
||||
|
||||
if (peer_vlan == NULL)
|
||||
{
|
||||
@ -126,14 +122,9 @@ static int iccp_check_interface_vlan(char* ifname)
|
||||
}
|
||||
}
|
||||
|
||||
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next)
|
||||
RB_FOREACH (peer_vlan, vlan_rb_tree, &(peer_if->vlan_tree))
|
||||
{
|
||||
|
||||
LIST_FOREACH(local_vlan, &(local_if->vlan_list), port_next)
|
||||
{
|
||||
if (peer_vlan->vid == local_vlan->vid)
|
||||
break;
|
||||
}
|
||||
local_vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), peer_vlan);
|
||||
|
||||
if (local_vlan == NULL)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@
|
||||
*
|
||||
* Maintainer: jianjun, grace Li from nephos
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include "../include/scheduler.h"
|
||||
#include "../include/msg_format.h"
|
||||
#include "../include/iccp_csm.h"
|
||||
#include "../include/iccp_cli.h"
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
/*****************************************
|
||||
* Define
|
||||
@ -121,6 +122,8 @@ void iccp_csm_init(struct CSM* csm)
|
||||
memset(csm->peer_ip, 0, INET_ADDRSTRLEN);
|
||||
memset(csm->iccp_info.sender_name, 0, MAX_L_ICC_SENDER_NAME);
|
||||
csm->iccp_info.icc_rg_id = 0x0;
|
||||
csm->keepalive_time = CONNECT_INTERVAL_SEC;
|
||||
csm->session_timeout = HEARTBEAT_TIMEOUT_SEC;
|
||||
}
|
||||
|
||||
/* Connection State Machine instance status reset */
|
||||
@ -141,6 +144,8 @@ void iccp_csm_status_reset(struct CSM* csm, int all)
|
||||
csm->heartbeat_update_time = 0;
|
||||
csm->peer_warm_reboot_time = 0;
|
||||
csm->warm_reboot_disconn_time = 0;
|
||||
csm->peer_link_learning_retry_time = 0;
|
||||
csm->peer_link_learning_enable = 0;
|
||||
csm->role_type = STP_ROLE_NONE;
|
||||
csm->sock_read_event_ptr = NULL;
|
||||
csm->peer_link_if = NULL;
|
||||
@ -165,6 +170,9 @@ void iccp_csm_finalize(struct CSM* csm)
|
||||
{
|
||||
struct If_info * cif = NULL;
|
||||
struct System* sys = NULL;
|
||||
struct LocalInterface* lifp = NULL;
|
||||
struct LocalInterface* local_if = NULL;
|
||||
struct LocalInterface* local_if_next = NULL;
|
||||
|
||||
if (csm == NULL)
|
||||
return;
|
||||
@ -176,21 +184,40 @@ void iccp_csm_finalize(struct CSM* csm)
|
||||
if (sys->warmboot_exit != WARM_REBOOT)
|
||||
{
|
||||
/*Enable peer link port MAC learning*/
|
||||
if (csm->peer_link_if)
|
||||
if (csm->peer_link_if) {
|
||||
set_peerlink_mlag_port_learn(csm->peer_link_if, 1);
|
||||
set_peerlink_learn_kernel(csm, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disconnect from peer */
|
||||
scheduler_session_disconnect_handler(csm);
|
||||
|
||||
//Delete all MCLAG interfaces
|
||||
local_if = LIST_FIRST(&(MLACP(csm).lif_list));
|
||||
while (local_if != NULL)
|
||||
{
|
||||
local_if_next = LIST_NEXT(local_if,mlacp_next);
|
||||
iccp_cli_detach_mclag_domain_to_port_channel(local_if->name);
|
||||
local_if = local_if_next;
|
||||
}
|
||||
|
||||
/* Release all Connection State Machine instance */
|
||||
app_csm_finalize(csm);
|
||||
|
||||
LIST_FOREACH(cif, &(csm->if_bind_list), csm_next)
|
||||
LIST_FOREACH(lifp, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
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 */
|
||||
pthread_mutex_destroy(&(csm->conn_mutex));
|
||||
iccp_csm_msg_list_finalize(csm);
|
||||
@ -219,6 +246,8 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
|
||||
{
|
||||
LDPHdr* ldp_hdr = (LDPHdr*)buf;
|
||||
ICCParameter* param = NULL;
|
||||
ssize_t rc;
|
||||
uint16_t tlv_type;
|
||||
|
||||
if (csm == NULL || buf == NULL || csm->sock_fd <= 0 || msg_len <= 0)
|
||||
return MCLAG_ERROR;
|
||||
@ -228,7 +257,7 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
|
||||
else
|
||||
param = (struct ICCParameter*)&buf[sizeof(ICCHdr)];
|
||||
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(param->type), ldp_hdr->msg_type, param->type);*/
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send(%d): len=[%d] msg_type=[%s (0x%X, 0x%X)]", csm->sock_fd, msg_len, get_tlv_type_string(ntohs(param->type)), ldp_hdr->msg_type, ntohs(param->type));
|
||||
csm->msg_log.msg[csm->msg_log.end_index].msg_id = ntohl(ldp_hdr->msg_id);
|
||||
csm->msg_log.msg[csm->msg_log.end_index].type = ntohs(ldp_hdr->msg_type);
|
||||
csm->msg_log.msg[csm->msg_log.end_index].tlv = ntohs(param->type);
|
||||
@ -236,7 +265,20 @@ int iccp_csm_send(struct CSM* csm, char* buf, int msg_len)
|
||||
if (csm->msg_log.end_index >= 128)
|
||||
csm->msg_log.end_index = 0;
|
||||
|
||||
return write(csm->sock_fd, buf, msg_len);
|
||||
tlv_type = ntohs(param->type);
|
||||
rc = write(csm->sock_fd, buf, msg_len);
|
||||
if ((rc <= 0) || (rc != msg_len))
|
||||
{
|
||||
MLACP_SET_ICCP_TX_DBG_COUNTER(
|
||||
csm, tlv_type, ICCP_DBG_CNTR_STS_ERR);
|
||||
ICCPD_LOG_ERR("ICCP_FSM", "Failed to write msg %s/0x%x, msg_len:%d, rc %d Error:%s ", get_tlv_type_string(tlv_type), tlv_type, msg_len, rc, strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
MLACP_SET_ICCP_TX_DBG_COUNTER(
|
||||
csm, tlv_type, ICCP_DBG_CNTR_STS_OK);
|
||||
}
|
||||
return (rc);
|
||||
}
|
||||
|
||||
/* Connection State Machine Transition */
|
||||
@ -776,8 +818,34 @@ int iccp_csm_init_msg(struct Msg** msg, char* data, int len)
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
/* MAC Message initialization */
|
||||
int iccp_csm_init_mac_msg(struct MACMsg **mac_msg, char* data, int len)
|
||||
{
|
||||
struct MACMsg* iccp_mac_msg = NULL;
|
||||
|
||||
if (mac_msg == NULL)
|
||||
return -2;
|
||||
|
||||
if (data == NULL || len <= 0)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
iccp_mac_msg = (struct MACMsg*)malloc(sizeof(struct MACMsg));
|
||||
if (iccp_mac_msg == NULL)
|
||||
return -3;
|
||||
|
||||
memset(iccp_mac_msg, 0, sizeof(struct MACMsg));
|
||||
memcpy(iccp_mac_msg, data, len);
|
||||
|
||||
*mac_msg = iccp_mac_msg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void iccp_csm_stp_role_count(struct CSM *csm)
|
||||
{
|
||||
struct If_info * cif = NULL;
|
||||
|
||||
/* decide the role, lower ip to be active & socket client*/
|
||||
if (csm->role_type == STP_ROLE_NONE)
|
||||
{
|
||||
@ -786,12 +854,18 @@ void iccp_csm_stp_role_count(struct CSM *csm)
|
||||
/* Active*/
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "Role: [Active]");
|
||||
csm->role_type = STP_ROLE_ACTIVE;
|
||||
/* Send ICCP role update and system ID */
|
||||
mlacp_link_set_iccp_role(csm->mlag_id, true, MLACP(csm).system_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standby*/
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "Role [Standby]");
|
||||
csm->role_type = STP_ROLE_STANDBY;
|
||||
/* Send ICCP role update */
|
||||
mlacp_link_set_iccp_role(csm->mlag_id, false, NULL);
|
||||
/*Set Bridge MAC to MY MAC*/
|
||||
mlacp_fix_bridge_mac(csm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -134,6 +134,7 @@ void iccpd_signal_handler(int sig)
|
||||
if (err == -1 && errno == EINTR)
|
||||
goto retry;
|
||||
|
||||
SYSTEM_INCR_WARMBOOT_COUNTER(sys);
|
||||
return;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@ static uint32_t _iccpd_log_level_map[] =
|
||||
LOG_WARNING,
|
||||
LOG_NOTICE,
|
||||
LOG_INFO,
|
||||
LOG_DEBUG,
|
||||
LOG_DEBUG
|
||||
};
|
||||
|
||||
char* log_level_to_string(int level)
|
||||
@ -100,7 +100,7 @@ void log_finalize()
|
||||
/*do nothing*/
|
||||
}
|
||||
|
||||
void write_log(const int level, const char* tag, const char* format, ...)
|
||||
void write_log(int level, const char* tag, const char* format, ...)
|
||||
{
|
||||
struct LoggerConfig* config = logger_get_configuration();
|
||||
char buf[LOGBUF_SIZE];
|
||||
|
@ -29,7 +29,11 @@
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "mclagdctl.h"
|
||||
#include "../../include/mlacp_fsm.h"
|
||||
#include "../../include/system.h"
|
||||
|
||||
static int mclagdctl_sock_fd = -1;
|
||||
char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock";
|
||||
@ -38,11 +42,25 @@ char *mclagdctl_sock_path = "/var/run/iccpd/mclagdctl.sock";
|
||||
Already implemented command:
|
||||
mclagdctl -i dump state
|
||||
mclagdctl -i dump arp
|
||||
mclagdctl -i dump nd
|
||||
mclagdctl -i dump mac
|
||||
mclagdctl -i dump unique_ip
|
||||
mclagdctl -i dump portlist local
|
||||
mclagdctl -i dump portlist peer
|
||||
*/
|
||||
|
||||
#define ETHER_ADDR_LEN 6
|
||||
char mac_print_str[18];
|
||||
|
||||
char *mac_addr_to_str(uint8_t* mac_addr)
|
||||
{
|
||||
memset(mac_print_str, 0, sizeof(mac_print_str));
|
||||
snprintf(mac_print_str, sizeof(mac_print_str), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
|
||||
return mac_print_str;
|
||||
}
|
||||
|
||||
static struct command_type command_types[] =
|
||||
{
|
||||
{
|
||||
@ -68,13 +86,13 @@ static struct command_type command_types[] =
|
||||
.parse_msg = mclagdctl_parse_dump_arp,
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_D_A,
|
||||
.parent_id = ID_CMDTYPE_D,
|
||||
.info_type = INFO_TYPE_DUMP_NDISC,
|
||||
.name = "nd",
|
||||
.enca_msg = mclagdctl_enca_dump_ndisc,
|
||||
.parse_msg = mclagdctl_parse_dump_ndisc,
|
||||
},
|
||||
.id = ID_CMDTYPE_D_A,
|
||||
.parent_id = ID_CMDTYPE_D,
|
||||
.info_type = INFO_TYPE_DUMP_NDISC,
|
||||
.name = "nd",
|
||||
.enca_msg = mclagdctl_enca_dump_ndisc,
|
||||
.parse_msg = mclagdctl_parse_dump_ndisc,
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_D_A,
|
||||
.parent_id = ID_CMDTYPE_D,
|
||||
@ -83,6 +101,14 @@ static struct command_type command_types[] =
|
||||
.enca_msg = mclagdctl_enca_dump_mac,
|
||||
.parse_msg = mclagdctl_parse_dump_mac,
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_D_A,
|
||||
.parent_id = ID_CMDTYPE_D,
|
||||
.info_type = INFO_TYPE_DUMP_UNIQUE_IP,
|
||||
.name = "unique_ip",
|
||||
.enca_msg = mclagdctl_enca_dump_unique_ip,
|
||||
.parse_msg = mclagdctl_parse_dump_unique_ip,
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_D_P,
|
||||
.parent_id = ID_CMDTYPE_D,
|
||||
@ -104,6 +130,19 @@ static struct command_type command_types[] =
|
||||
.enca_msg = mclagdctl_enca_dump_peer_portlist,
|
||||
.parse_msg = mclagdctl_parse_dump_peer_portlist,
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_D_D,
|
||||
.parent_id = ID_CMDTYPE_D,
|
||||
.name = "debug",
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_D_D_C,
|
||||
.parent_id = ID_CMDTYPE_D_D,
|
||||
.info_type = INFO_TYPE_DUMP_DBG_COUNTERS,
|
||||
.name = "counters",
|
||||
.enca_msg = mclagdctl_enca_dump_dbg_counters,
|
||||
.parse_msg = mclagdctl_parse_dump_dbg_counters,
|
||||
},
|
||||
{
|
||||
.id = ID_CMDTYPE_C,
|
||||
.name = "config",
|
||||
@ -117,7 +156,7 @@ static struct command_type command_types[] =
|
||||
.name = "loglevel",
|
||||
.enca_msg = mclagdctl_enca_config_loglevel,
|
||||
.parse_msg = mclagdctl_parse_config_loglevel,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
@ -250,8 +289,18 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
|
||||
{
|
||||
state_info = (struct mclagd_state*)(msg + len * count);
|
||||
|
||||
fprintf(stdout, "%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR");
|
||||
if (inet_addr(state_info->local_ip) < inet_addr(state_info->peer_ip))
|
||||
{
|
||||
state_info->role = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state_info->role = 2;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s: %s\n", "The MCLAG's keepalive is", state_info->keepalive ? "OK" : "ERROR");
|
||||
fprintf(stdout, "%s: %s\n", "MCLAG info sync is",
|
||||
state_info->info_sync_done ? "completed" : "incomplete");
|
||||
if (state_info->mclag_id <= 0)
|
||||
fprintf(stdout, "%s: %s\n", "Domain id", "Unknown");
|
||||
else
|
||||
@ -260,6 +309,8 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
|
||||
fprintf(stdout, "%s: %s\n", "Local Ip", state_info->local_ip);
|
||||
fprintf(stdout, "%s: %s\n", "Peer Ip", state_info->peer_ip);
|
||||
fprintf(stdout, "%s: %s\n", "Peer Link Interface", state_info->peer_link_if);
|
||||
fprintf(stdout, "%s: %d\n", "Keepalive time", state_info->keepalive_time);
|
||||
fprintf(stdout, "%s: %d\n", "sesssion Timeout ", state_info->session_timeout);
|
||||
|
||||
fprintf(stdout, "%s: %02x:%02x:%02x:%02x:%02x:%02x \n",
|
||||
"Peer Link Mac",
|
||||
@ -267,9 +318,10 @@ int mclagdctl_parse_dump_state(char *msg, int data_len)
|
||||
state_info->peer_link_mac[2], state_info->peer_link_mac[3],
|
||||
state_info->peer_link_mac[4], state_info->peer_link_mac[5]);
|
||||
|
||||
if (state_info->role == 0)
|
||||
/*if (state_info->role == 0)
|
||||
fprintf(stdout, "%s: %s\n", "Role", "None");
|
||||
else if (state_info->role == 1)
|
||||
*/
|
||||
if (state_info->role == 1)
|
||||
fprintf(stdout, "%s: %s\n", "Role", "Active");
|
||||
else if (state_info->role == 2)
|
||||
fprintf(stdout, "%s: %s\n", "Role", "Standby");
|
||||
@ -328,6 +380,7 @@ int mclagdctl_parse_dump_arp(char *msg, int data_len)
|
||||
fprintf(stdout, "%-20s", "IP");
|
||||
fprintf(stdout, "%-20s", "MAC");
|
||||
fprintf(stdout, "%-20s", "DEV");
|
||||
fprintf(stdout, "%s", "Flag");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
len = sizeof(struct mclagd_arp_msg);
|
||||
@ -344,6 +397,13 @@ int mclagdctl_parse_dump_arp(char *msg, int data_len)
|
||||
arp_info->mac_addr[4], arp_info->mac_addr[5]);
|
||||
fprintf(stdout, " ");
|
||||
fprintf(stdout, "%-20s", arp_info->ifname);
|
||||
if (arp_info->learn_flag == NEIGH_REMOTE) {
|
||||
fprintf(stdout, "%s", "R");
|
||||
} else if (arp_info->learn_flag == NEIGH_LOCAL) {
|
||||
fprintf(stdout, "%s", "L");
|
||||
} else {
|
||||
fprintf(stdout, "%s", "-");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
@ -360,6 +420,7 @@ int mclagdctl_parse_dump_ndisc(char *msg, int data_len)
|
||||
fprintf(stdout, "%-52s", "IPv6");
|
||||
fprintf(stdout, "%-20s", "MAC");
|
||||
fprintf(stdout, "%-20s", "DEV");
|
||||
fprintf(stdout, "%s", "Flag");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
len = sizeof(struct mclagd_ndisc_msg);
|
||||
@ -372,10 +433,16 @@ int mclagdctl_parse_dump_ndisc(char *msg, int data_len)
|
||||
fprintf(stdout, "%-52s", ndisc_info->ipv6_addr);
|
||||
fprintf(stdout, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
ndisc_info->mac_addr[0], ndisc_info->mac_addr[1],
|
||||
ndisc_info->mac_addr[2], ndisc_info->mac_addr[3],
|
||||
ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]);
|
||||
ndisc_info->mac_addr[2], ndisc_info->mac_addr[3], ndisc_info->mac_addr[4], ndisc_info->mac_addr[5]);
|
||||
fprintf(stdout, " ");
|
||||
fprintf(stdout, "%-20s", ndisc_info->ifname);
|
||||
if (ndisc_info->learn_flag == NEIGH_REMOTE) {
|
||||
fprintf(stdout, "%s", "R");
|
||||
} else if (ndisc_info->learn_flag == NEIGH_LOCAL) {
|
||||
fprintf(stdout, "%s", "L");
|
||||
} else {
|
||||
fprintf(stdout, "%s", "-");
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
@ -430,7 +497,8 @@ int mclagdctl_parse_dump_mac(char *msg, int data_len)
|
||||
else
|
||||
fprintf(stdout, "%-5s", "D");
|
||||
|
||||
fprintf(stdout, "%-20s", mac_info->mac_str);
|
||||
fprintf(stdout, "%-20s", mac_addr_to_str(mac_info->mac_addr));
|
||||
|
||||
fprintf(stdout, "%-5d", mac_info->vid);
|
||||
fprintf(stdout, "%-20s", mac_info->ifname);
|
||||
fprintf(stdout, "%-20s", mac_info->origin_ifname);
|
||||
@ -502,10 +570,11 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len)
|
||||
fprintf(stdout, "%s: %s\n", "IsL3Interface", lif_info->l3_mode ? "Yes" : "No");
|
||||
/*fprintf(stdout, "%s: %s\n", "IsPeerlink", lif_info->is_peer_link ? "Yes" : "No");*/
|
||||
fprintf(stdout, "%s: %s\n", "MemberPorts", lif_info->portchannel_member_buf);
|
||||
/*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);
|
||||
fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active);
|
||||
fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/
|
||||
/*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/
|
||||
fprintf(stdout,"%s: %d\n" ,"PortchannelIsUp", lif_info->po_active);
|
||||
/*fprintf(stdout,"%s: %s\n", "MlacpState", lif_info->mlacp_state);*/
|
||||
fprintf(stdout, "%s: %s\n", "IsIsolateWithPeerlink", lif_info->isolate_to_peer_link ? "Yes" : "No");
|
||||
fprintf(stdout,"%s: %s\n" ,"IsTrafficDisable", lif_info->is_traffic_disable ? "Yes":"No");
|
||||
fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist);
|
||||
}
|
||||
else
|
||||
@ -514,6 +583,7 @@ int mclagdctl_parse_dump_local_portlist(char *msg, int data_len)
|
||||
fprintf(stdout, "%s: %s\n", "Type", lif_info->type);
|
||||
fprintf(stdout, "%s: %s\n", "PortName", lif_info->name);
|
||||
fprintf(stdout, "%s: %s\n", "State", lif_info->state);
|
||||
fprintf(stdout, "%s: %s\n", "VlanList", lif_info->vlanlist);
|
||||
/*fprintf(stdout,"%s: %d\n" ,"PortchannelId", lif_info->po_id);*/
|
||||
}
|
||||
|
||||
@ -584,6 +654,277 @@ int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mclagdctl_enca_dump_unique_ip(char *msg, int mclag_id, int argc, char **argv)
|
||||
{
|
||||
struct mclagdctl_req_hdr req;
|
||||
|
||||
if (mclag_id <= 0)
|
||||
{
|
||||
fprintf(stderr, "Need to specify mclag-id through the parameter i !\n");
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(struct mclagdctl_req_hdr));
|
||||
req.info_type = INFO_TYPE_DUMP_UNIQUE_IP;
|
||||
req.mclag_id = mclag_id;
|
||||
memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mclagdctl_parse_dump_unique_ip(char *msg, int data_len)
|
||||
{
|
||||
struct mclagd_unique_ip_if *ip_if_info = NULL;
|
||||
int len = 0;
|
||||
int count = 0;
|
||||
int pos = 0;
|
||||
|
||||
for (pos = 0; pos < 60; ++pos)
|
||||
fprintf(stdout, "-");
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, "%-20s", "Ifname");
|
||||
fprintf(stdout, "%-5s", "Active");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
for (pos = 0; pos < 60; ++pos)
|
||||
fprintf(stdout, "-");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
len = sizeof(struct mclagd_unique_ip_if);
|
||||
|
||||
for (; data_len >= len; data_len -= len, count++)
|
||||
{
|
||||
ip_if_info = (struct mclagd_unique_ip_if*)(msg + len * count);
|
||||
|
||||
fprintf(stdout, "%-20s %-5s\n", ip_if_info->name, ip_if_info->active?"Yes":"No");
|
||||
}
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
fprintf(stdout, "%s\n", "Unique IP configuration not enabled on any interface");
|
||||
}
|
||||
|
||||
for (pos = 0; pos < 60; ++pos)
|
||||
fprintf(stdout, "-");
|
||||
|
||||
fprintf(stdout, "\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mclag_id parameter is optional */
|
||||
int mclagdctl_enca_dump_dbg_counters(char *msg, int mclag_id, int argc, char **argv)
|
||||
{
|
||||
struct mclagdctl_req_hdr req;
|
||||
|
||||
memset(&req, 0, sizeof(struct mclagdctl_req_hdr));
|
||||
req.info_type = INFO_TYPE_DUMP_DBG_COUNTERS;
|
||||
req.mclag_id = mclag_id;
|
||||
memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *mclagdctl_dbg_counter_iccpid2str(ICCP_DBG_CNTR_MSG_e iccp_cntr_id)
|
||||
{
|
||||
/* Keep the string to 15 characters.
|
||||
* Update mclagdctl_parse_dump_dbg_counters if increase
|
||||
*/
|
||||
switch(iccp_cntr_id)
|
||||
{
|
||||
case ICCP_DBG_CNTR_MSG_SYS_CONFIG:
|
||||
return "SysConfig";
|
||||
case ICCP_DBG_CNTR_MSG_AGGR_CONFIG:
|
||||
return "AggrConfig";
|
||||
case ICCP_DBG_CNTR_MSG_AGGR_STATE:
|
||||
return "AggrState";
|
||||
case ICCP_DBG_CNTR_MSG_MAC_INFO:
|
||||
return "MacInfo";
|
||||
case ICCP_DBG_CNTR_MSG_ARP_INFO:
|
||||
return "ArpInfo";
|
||||
case ICCP_DBG_CNTR_MSG_PORTCHANNEL_INFO:
|
||||
return "PoInfo";
|
||||
case ICCP_DBG_CNTR_MSG_PEER_LINK_INFO:
|
||||
return "PeerLinkInfo";
|
||||
case ICCP_DBG_CNTR_MSG_HEART_BEAT:
|
||||
return "Heartbeat";
|
||||
case ICCP_DBG_CNTR_MSG_NAK:
|
||||
return "Nak";
|
||||
case ICCP_DBG_CNTR_MSG_SYNC_DATA:
|
||||
return "SyncData";
|
||||
case ICCP_DBG_CNTR_MSG_SYNC_REQ:
|
||||
return "SyncReq";
|
||||
case ICCP_DBG_CNTR_MSG_WARM_BOOT:
|
||||
return "Warmboot";
|
||||
case ICCP_DBG_CNTR_MSG_IF_UP_ACK:
|
||||
return "IfUpAck";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static char *mclagdctl_dbg_counter_syncdtx2str(SYNCD_TX_DBG_CNTR_MSG_e syncdtx_id)
|
||||
{
|
||||
/* Keep the string to 20 characters.
|
||||
* Update mclagdctl_parse_dump_dbg_counters if increase
|
||||
*/
|
||||
switch(syncdtx_id)
|
||||
{
|
||||
case SYNCD_TX_DBG_CNTR_MSG_PORT_ISOLATE:
|
||||
return "PortIsolation";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_PORT_MAC_LEARN_MODE:
|
||||
return "MacLearnMode";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_FLUSH_FDB:
|
||||
return "FlushFdb";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_IF_MAC:
|
||||
return "SetIfMac";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_FDB:
|
||||
return "SetFdb";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_ENABLE:
|
||||
return "TrafficDistEnable";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_DISABLE:
|
||||
return "TrafficDistDisable";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_STATE:
|
||||
return "SetIccpState";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_ROLE:
|
||||
return "SetIccpRole";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_SYSTEM_ID:
|
||||
return "SetSystemId";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_DEL_ICCP_INFO:
|
||||
return "DelIccpInfo";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_REMOTE_IF_STATE:
|
||||
return "SetRemoteIntfSts";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_DEL_REMOTE_IF_INFO:
|
||||
return "DelRemoteIntf";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_PEER_LINK_ISOLATION:
|
||||
return "PeerLinkIsolation";
|
||||
case SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_PEER_SYSTEM_ID:
|
||||
return "SetPeerSystemId";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static char *mclagdctl_dbg_counter_syncdrx2str(SYNCD_RX_DBG_CNTR_MSG_e syncdrx_id)
|
||||
{
|
||||
/* Keep the string to 20 characters.
|
||||
* Update mclagdctl_parse_dump_dbg_counters if increase
|
||||
*/
|
||||
switch(syncdrx_id)
|
||||
{
|
||||
case SYNCD_RX_DBG_CNTR_MSG_MAC:
|
||||
return "FdbChange";
|
||||
case SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_DOMAIN:
|
||||
return "CfgMclag";
|
||||
case SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_IFACE:
|
||||
return "CfgMclagIface";
|
||||
case SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_UNIQUE_IP:
|
||||
return "CfgMclagUniqueIp";
|
||||
case SYNCD_RX_DBG_CNTR_MSG_VLAN_MBR_UPDATES:
|
||||
return "vlanMbrshipChange";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int mclagdctl_parse_dump_dbg_counters(char *msg, int data_len)
|
||||
{
|
||||
mclagd_dbg_counter_info_t *dbg_counter_p;
|
||||
system_dbg_counter_info_t *sys_counter_p;
|
||||
mlacp_dbg_counter_info_t *iccp_counter_p;
|
||||
int i, j;
|
||||
|
||||
dbg_counter_p = (mclagd_dbg_counter_info_t *)msg;
|
||||
sys_counter_p = (system_dbg_counter_info_t *)&dbg_counter_p->system_dbg;
|
||||
|
||||
/* Global counters */
|
||||
fprintf(stdout, "%-20s%u\n", "ICCP session down:",
|
||||
sys_counter_p->session_down_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Peer link down:",
|
||||
sys_counter_p->peer_link_down_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx invalid msg:",
|
||||
sys_counter_p->rx_peer_invalid_msg_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx sock error(hdr):",
|
||||
sys_counter_p->rx_peer_hdr_read_sock_err_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx zero len(hdr):",
|
||||
sys_counter_p->rx_peer_hdr_read_sock_zero_len_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx sock error(tlv):",
|
||||
sys_counter_p->rx_peer_tlv_read_sock_err_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx zero len(tlv):",
|
||||
sys_counter_p->rx_peer_tlv_read_sock_zero_len_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx retry max:",
|
||||
sys_counter_p->rx_retry_max_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx retry total:",
|
||||
sys_counter_p->rx_retry_total_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Rx retry fail:",
|
||||
sys_counter_p->rx_retry_fail_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Socket close err:",
|
||||
sys_counter_p->socket_close_err_counter);
|
||||
fprintf(stdout, "%-20s%u\n", "Socket cleanup:",
|
||||
sys_counter_p->socket_cleanup_counter);
|
||||
|
||||
fprintf(stdout, "\n");
|
||||
fprintf(stdout, "%-20s%u\n\n", "Warmboot:", sys_counter_p->warmboot_counter);
|
||||
|
||||
/* ICCP daemon to Mclagsyncd messages */
|
||||
fprintf(stdout, "%-20s%-20s%-20s\n", "ICCP to MclagSyncd", "TX_OK", "TX_ERROR");
|
||||
fprintf(stdout, "%-20s%-20s%-20s\n", "------------------", "-----", "--------");
|
||||
for (i = 0; i < SYNCD_TX_DBG_CNTR_MSG_MAX; ++i)
|
||||
{
|
||||
fprintf(stdout, "%-20s%-20lu%-20lu\n",
|
||||
mclagdctl_dbg_counter_syncdtx2str(i),
|
||||
sys_counter_p->syncd_tx_counters[i][0],
|
||||
sys_counter_p->syncd_tx_counters[i][1]);
|
||||
}
|
||||
|
||||
fprintf(stdout, "\n%-20s%-20s%-20s\n", "MclagSyncd to ICCP", "RX_OK", "RX_ERROR");
|
||||
fprintf(stdout, "%-20s%-20s%-20s\n", "------------------", "-----", "--------");
|
||||
for (i = 0; i < SYNCD_RX_DBG_CNTR_MSG_MAX; ++i)
|
||||
{
|
||||
fprintf(stdout, "%-20s%-20lu%-20lu\n",
|
||||
mclagdctl_dbg_counter_syncdrx2str(i),
|
||||
sys_counter_p->syncd_rx_counters[i][0],
|
||||
sys_counter_p->syncd_rx_counters[i][1]);
|
||||
}
|
||||
/* Print ICCP messages exchanged between MLAG peers */
|
||||
fprintf(stdout, "\n%-20s%-20s%-20s%-20s%-20s\n",
|
||||
"ICCP to Peer", "TX_OK", "RX_OK", "TX_ERROR", "RX_ERROR");
|
||||
fprintf(stdout, "%-20s%-20s%-20s%-20s%-20s\n",
|
||||
"------------", "-----", "-----", "--------", "--------");
|
||||
|
||||
iccp_counter_p = (mlacp_dbg_counter_info_t *)dbg_counter_p->iccp_dbg_counters;
|
||||
for (i = 0; i < dbg_counter_p->num_iccp_counter_blocks; ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
++iccp_counter_p;
|
||||
|
||||
for (j = 0; j < ICCP_DBG_CNTR_MSG_MAX; ++j)
|
||||
{
|
||||
fprintf(stdout, "%-20s%-20lu%-20lu%-20lu%-20lu\n",
|
||||
mclagdctl_dbg_counter_iccpid2str(j),
|
||||
iccp_counter_p->iccp_counters[j][0][0],
|
||||
iccp_counter_p->iccp_counters[j][1][0],
|
||||
iccp_counter_p->iccp_counters[j][0][1],
|
||||
iccp_counter_p->iccp_counters[j][1][1]);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
/* Netlink counters */
|
||||
fprintf(stdout, "\nNetlink Counters\n");
|
||||
fprintf(stdout, "-----------------\n");
|
||||
fprintf(stdout, "Link add/del: %u/%u\n",
|
||||
sys_counter_p->newlink_count, sys_counter_p->dellink_count);
|
||||
fprintf(stdout, " Unknown if_name: %u\n", sys_counter_p->unknown_if_name_count);
|
||||
fprintf(stdout, "Neighbor(ARP) add/del: %u/%u\n",
|
||||
sys_counter_p->newnbr_count, sys_counter_p->delnbr_count);
|
||||
fprintf(stdout, " MAC entry add/del: %u/%u\n",
|
||||
sys_counter_p->newmac_count, sys_counter_p->delmac_count);
|
||||
fprintf(stdout, "Address add/del: %u/%u\n",
|
||||
sys_counter_p->newaddr_count, sys_counter_p->deladdr_count);
|
||||
fprintf(stdout, "Unexpected message type: %u\n", sys_counter_p->unknown_type_count);
|
||||
fprintf(stdout, "Receive error: %u\n\n", sys_counter_p->rx_error_count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv)
|
||||
{
|
||||
struct mclagdctl_req_hdr req;
|
||||
@ -940,4 +1281,3 @@ int main(int argc, char **argv)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,11 @@
|
||||
*
|
||||
* Maintainer: Jim Jiang from nephos
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../include/system.h"
|
||||
|
||||
#define ETHER_ADDR_LEN 6
|
||||
#define MCLAGDCTL_PARA1_LEN 16
|
||||
#define MCLAGDCTL_PARA2_LEN 32
|
||||
#define MCLAGDCTL_PARA3_LEN 64
|
||||
@ -54,8 +58,11 @@ enum id_command_type
|
||||
ID_CMDTYPE_D_P,
|
||||
ID_CMDTYPE_D_P_L,
|
||||
ID_CMDTYPE_D_P_P,
|
||||
ID_CMDTYPE_D_D,
|
||||
ID_CMDTYPE_D_D_C,
|
||||
ID_CMDTYPE_C,
|
||||
ID_CMDTYPE_C_L,
|
||||
ID_CMDTYPE_C_D,
|
||||
};
|
||||
|
||||
enum mclagdctl_notify_peer_type
|
||||
@ -65,9 +72,12 @@ enum mclagdctl_notify_peer_type
|
||||
INFO_TYPE_DUMP_ARP,
|
||||
INFO_TYPE_DUMP_NDISC,
|
||||
INFO_TYPE_DUMP_MAC,
|
||||
INFO_TYPE_DUMP_UNIQUE_IP,
|
||||
INFO_TYPE_DUMP_LOCAL_PORTLIST,
|
||||
INFO_TYPE_DUMP_PEER_PORTLIST,
|
||||
INFO_TYPE_DUMP_DBG_COUNTERS,
|
||||
INFO_TYPE_CONFIG_LOGLEVEL,
|
||||
INFO_TYPE_CONFIG_DOWN,
|
||||
INFO_TYPE_FINISH,
|
||||
};
|
||||
|
||||
@ -122,21 +132,28 @@ struct mclagd_state
|
||||
{
|
||||
int mclag_id;
|
||||
int keepalive;
|
||||
int info_sync_done;
|
||||
char local_ip[MCLAGDCTL_INET_ADDR_LEN];
|
||||
char peer_ip[MCLAGDCTL_INET_ADDR_LEN];
|
||||
char peer_link_if[MCLAGDCTL_MAX_L_PORT_NANE];
|
||||
unsigned char peer_link_mac[MCLAGDCTL_ETHER_ADDR_LEN];
|
||||
int role;
|
||||
char enabled_po[MCLAGDCTL_PORT_MEMBER_BUF_LEN];
|
||||
int session_timeout;
|
||||
int keepalive_time;
|
||||
char loglevel[MCLAGDCTL_PARA1_LEN];
|
||||
};
|
||||
|
||||
#define NEIGH_LOCAL 1
|
||||
#define NEIGH_REMOTE 2
|
||||
|
||||
struct mclagd_arp_msg
|
||||
{
|
||||
char op_type;
|
||||
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
|
||||
char ipv4_addr[MCLAGDCTL_INET_ADDR_LEN];
|
||||
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
|
||||
uint8_t learn_flag;
|
||||
};
|
||||
|
||||
struct mclagd_ndisc_msg
|
||||
@ -145,13 +162,14 @@ struct mclagd_ndisc_msg
|
||||
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
|
||||
char ipv6_addr[MCLAGDCTL_INET6_ADDR_LEN];
|
||||
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
|
||||
uint8_t learn_flag;
|
||||
};
|
||||
|
||||
struct mclagd_mac_msg
|
||||
{
|
||||
unsigned char op_type;/*add or del*/
|
||||
unsigned char fdb_type;/*static or dynamic*/
|
||||
char mac_str[ETHER_ADDR_STR_LEN];
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
unsigned short vid;
|
||||
/*Current if name that set in chip*/
|
||||
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
|
||||
@ -178,7 +196,7 @@ struct mclagd_local_if
|
||||
unsigned char po_active;
|
||||
char mlacp_state[MCLAGDCTL_PARA1_LEN];
|
||||
unsigned char isolate_to_peer_link;
|
||||
|
||||
bool is_traffic_disable;
|
||||
char vlanlist[MCLAGDCTL_PARA3_LEN];
|
||||
};
|
||||
|
||||
@ -193,6 +211,21 @@ struct mclagd_peer_if
|
||||
unsigned char po_active;
|
||||
};
|
||||
|
||||
typedef struct mclagd_dbg_counter_info
|
||||
{
|
||||
system_dbg_counter_info_t system_dbg;
|
||||
uint8_t num_iccp_counter_blocks;
|
||||
uint8_t iccp_dbg_counters[0];
|
||||
/* Variable length counter buffers containing N mlacp_dbg_counter_info_t
|
||||
*/
|
||||
}mclagd_dbg_counter_info_t;
|
||||
|
||||
struct mclagd_unique_ip_if
|
||||
{
|
||||
int active;
|
||||
char name[MCLAGDCTL_MAX_L_PORT_NANE];
|
||||
};
|
||||
|
||||
extern int mclagdctl_enca_dump_state(char *msg, int mclag_id, int argc, char **argv);
|
||||
extern int mclagdctl_parse_dump_state(char *msg, int data_len);
|
||||
extern int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv);
|
||||
@ -208,3 +241,7 @@ extern int mclagdctl_parse_dump_peer_portlist(char *msg, int data_len);
|
||||
int mclagdctl_enca_config_loglevel(char *msg, int log_level, int argc, char **argv);
|
||||
int mclagdctl_parse_config_loglevel(char *msg, int data_len);
|
||||
|
||||
extern int mclagdctl_enca_dump_dbg_counters(char *msg, int mclag_id, int argc, char **argv);
|
||||
extern int mclagdctl_parse_dump_dbg_counters(char *msg, int data_len);
|
||||
extern int mclagdctl_enca_dump_unique_ip(char *msg, int mclag_id, int argc, char **argv);
|
||||
extern int mclagdctl_parse_dump_unique_ip(char *msg, int data_len);
|
||||
|
@ -35,10 +35,13 @@
|
||||
#include <msg_format.h>
|
||||
#include <system.h>
|
||||
#include <logger.h>
|
||||
#include <assert.h>
|
||||
#include "../include/mlacp_tlv.h"
|
||||
#include "../include/mlacp_sync_prepare.h"
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
#include "../include/mlacp_sync_update.h"
|
||||
#include "../include/system.h"
|
||||
#include "../include/scheduler.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
@ -58,6 +61,18 @@
|
||||
TAILQ_INIT(&(list)); \
|
||||
}
|
||||
|
||||
#define MLACP_MAC_MSG_QUEUE_REINIT(list) \
|
||||
{ \
|
||||
struct MACMsg* mac_msg = NULL; \
|
||||
while (!TAILQ_EMPTY(&(list))) { \
|
||||
mac_msg = TAILQ_FIRST(&(list)); \
|
||||
TAILQ_REMOVE(&(list), mac_msg, tail); \
|
||||
if (mac_msg->op_type == MAC_SYNC_DEL) \
|
||||
free(mac_msg); \
|
||||
} \
|
||||
TAILQ_INIT(&(list)); \
|
||||
}
|
||||
|
||||
#define PIF_QUEUE_REINIT(list) \
|
||||
{ \
|
||||
while (!LIST_EMPTY(&(list))) { \
|
||||
@ -76,7 +91,7 @@
|
||||
lif = LIST_FIRST(&(list)); \
|
||||
if (lif->type == IF_T_PORT_CHANNEL && lif->is_arp_accept) { \
|
||||
if ((set_sys_arp_accept_flag(lif->name, 0)) == 0) \
|
||||
lif->is_arp_accept = 0; \
|
||||
lif->is_arp_accept = 0; \
|
||||
} \
|
||||
LIST_REMOVE (lif, mlacp_next); \
|
||||
} \
|
||||
@ -93,22 +108,48 @@
|
||||
LIST_INIT(&(list)); \
|
||||
}
|
||||
|
||||
|
||||
void mlacp_local_lif_clear_pending_mac(struct CSM* csm, struct LocalInterface *local_lif);
|
||||
/*****************************************
|
||||
* Rb tree Functions
|
||||
*
|
||||
* ***************************************/
|
||||
|
||||
static int MACMsg_compare(const struct MACMsg *mac1, const struct MACMsg *mac2)
|
||||
{
|
||||
if (mac1->vid < mac2->vid)
|
||||
return -1;
|
||||
|
||||
if (mac1->vid > mac2->vid)
|
||||
return 1;
|
||||
|
||||
if(memcmp((char *)&mac1->mac_addr, (char *)&mac2->mac_addr, ETHER_ADDR_LEN) < 0)
|
||||
return -1;
|
||||
|
||||
if(memcmp((char *)&mac1->mac_addr, (char *)&mac2->mac_addr, ETHER_ADDR_LEN) > 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RB_GENERATE(mac_rb_tree, MACMsg, mac_entry_rb, MACMsg_compare);
|
||||
|
||||
#define WARM_REBOOT_TIMEOUT 90
|
||||
#define PEER_REBOOT_TIMEOUT 300
|
||||
|
||||
/*****************************************
|
||||
* Static Function
|
||||
*
|
||||
* ***************************************/
|
||||
static char *mlacp_state(struct CSM* csm);
|
||||
char *mlacp_state(struct CSM* csm);
|
||||
static void mlacp_resync_arp(struct CSM* csm);
|
||||
static void mlacp_resync_ndisc(struct CSM* csm);
|
||||
static void mlacp_resync_mac(struct CSM* csm);
|
||||
static void mlacp_resync_ndisc(struct CSM *csm);
|
||||
/* Sync Sender APIs*/
|
||||
static void mlacp_sync_send_sysConf(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_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_syncDoneData(struct CSM* csm);
|
||||
/* 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_exchange_handler(struct CSM* csm, struct Msg* msg);
|
||||
|
||||
void mlacp_local_lif_state_mac_handler(struct CSM* csm);
|
||||
|
||||
/* Interface up ack */
|
||||
static void mlacp_fsm_send_if_up_ack(
|
||||
struct CSM *csm,
|
||||
uint8_t if_type,
|
||||
uint16_t if_id,
|
||||
uint8_t port_isolation_enable);
|
||||
|
||||
/******************************************************************
|
||||
* Sync Sender APIs
|
||||
*
|
||||
@ -210,19 +260,35 @@ static void mlacp_sync_send_aggState(struct CSM* csm)
|
||||
static void mlacp_sync_send_syncMacInfo(struct CSM* csm)
|
||||
{
|
||||
int msg_len = 0;
|
||||
struct Msg* msg = NULL;
|
||||
struct MACMsg* mac_msg = NULL;
|
||||
struct MACMsg mac_find;
|
||||
int count = 0;
|
||||
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
memset(&mac_find, 0, sizeof(struct MACMsg));
|
||||
|
||||
while (!TAILQ_EMPTY(&(MLACP(csm).mac_msg_list)))
|
||||
{
|
||||
msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list));
|
||||
TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), msg, tail);
|
||||
msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct MACMsg*)msg->buf, count);
|
||||
mac_msg = TAILQ_FIRST(&(MLACP(csm).mac_msg_list));
|
||||
MAC_TAILQ_REMOVE(&(MLACP(csm).mac_msg_list), mac_msg, tail);
|
||||
|
||||
msg_len = mlacp_prepare_for_mac_info_to_peer(csm, g_csm_buf, CSM_BUFFER_SIZE, mac_msg, count);
|
||||
count++;
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
|
||||
//free mac_msg if marked for delete.
|
||||
if (mac_msg->op_type == MAC_SYNC_DEL)
|
||||
{
|
||||
if (!(mac_msg->mac_entry_rb.rbt_parent))
|
||||
{
|
||||
//If the entry is parent then the parent pointer would be null
|
||||
//search to confirm if the MAC is present in RB tree. if not then free.
|
||||
mac_find.vid = mac_msg->vid ;
|
||||
memcpy(mac_find.mac_addr, mac_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
if (!RB_FIND(mac_rb_tree, &MLACP(csm).mac_rb ,&mac_find))
|
||||
free(mac_msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (count >= MAX_MAC_ENTRY_NUM)
|
||||
{
|
||||
iccp_csm_send(csm, g_csm_buf, msg_len);
|
||||
@ -251,7 +317,7 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm)
|
||||
msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list));
|
||||
TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail);
|
||||
|
||||
msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf, count);
|
||||
msg_len = mlacp_prepare_for_arp_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct ARPMsg*)msg->buf, count, NEIGH_SYNC_CLIENT_IP);
|
||||
count++;
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
@ -283,7 +349,7 @@ static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
|
||||
msg = TAILQ_FIRST(&(MLACP(csm).ndisc_msg_list));
|
||||
TAILQ_REMOVE(&(MLACP(csm).ndisc_msg_list), msg, tail);
|
||||
|
||||
msg_len = mlacp_prepare_for_ndisc_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct NDISCMsg *)msg->buf, count);
|
||||
msg_len = mlacp_prepare_for_ndisc_info(csm, g_csm_buf, CSM_BUFFER_SIZE, (struct NDISCMsg *)msg->buf, count, NEIGH_SYNC_CLIENT_IP);
|
||||
count++;
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
@ -301,6 +367,7 @@ static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
@ -348,7 +415,7 @@ static void mlacp_sync_send_heartbeat(struct CSM* csm)
|
||||
int msg_len = 0;
|
||||
|
||||
if ((csm->heartbeat_send_time == 0) ||
|
||||
((time(NULL) - csm->heartbeat_send_time) > 1))
|
||||
((time(NULL) - csm->heartbeat_send_time) > csm->keepalive_time))
|
||||
{
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
msg_len = mlacp_prepare_for_heartbeat(csm, g_csm_buf, CSM_BUFFER_SIZE);
|
||||
@ -386,8 +453,15 @@ static void mlacp_sync_recv_sysConf(struct CSM* csm, struct Msg* msg)
|
||||
if (mlacp_fsm_update_system_conf(csm, sysconf) == MCLAG_ERROR)
|
||||
{
|
||||
/*NOTE: we just change the node ID local side without sending NAK msg*/
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id);
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "RX same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id);
|
||||
mlacp_sync_send_nak_handler(csm, msg);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
sysconf->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
sysconf->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -419,6 +493,13 @@ static void mlacp_sync_recv_aggConf(struct CSM* csm, struct Msg* msg)
|
||||
if (mlacp_fsm_update_Agg_conf(csm, portconf) == MCLAG_ERROR)
|
||||
{
|
||||
mlacp_sync_send_nak_handler(csm, msg);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -433,7 +514,22 @@ static void mlacp_sync_recv_aggState(struct CSM* csm, struct Msg* msg)
|
||||
{
|
||||
mlacp_sync_send_nak_handler(csm, msg);
|
||||
/*MLACP(csm).error_msg = "Receive a port state update on an non-existed port. It is suggest to check the environment and re-initialize mLACP again.";*/
|
||||
return;
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
portstate->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
portstate->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
}
|
||||
/* Send interface up ack for MLAG interface regardless of the
|
||||
* processing return code
|
||||
*/
|
||||
if (portstate->agg_state == PORT_STATE_UP)
|
||||
{
|
||||
mlacp_fsm_send_if_up_ack(
|
||||
csm, IF_UP_ACK_TYPE_PORT_CHANNEL, ntohs(portstate->agg_id),
|
||||
PORT_ISOLATION_STATE_ENABLE);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -448,7 +544,12 @@ static void mlacp_sync_recv_syncData(struct CSM* csm, struct Msg* msg)
|
||||
{
|
||||
/* Sync done*/
|
||||
MLACP(csm).wait_for_sync_data = 0;
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "RX sync done");
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "RX sync start");
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
syncdata->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -460,8 +561,13 @@ static void mlacp_sync_recv_syncReq(struct CSM* csm, struct Msg* msg)
|
||||
mlacp_sync_req = (mLACPSyncReqTLV*)&msg->buf[sizeof(ICCHdr)];
|
||||
MLACP(csm).sync_req_num = ntohs(mlacp_sync_req->req_num);
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "RX sync_requrest: req_no %d",
|
||||
MLACP(csm).sync_req_num);
|
||||
|
||||
/* Reply the peer all sync info*/
|
||||
mlacp_sync_send_all_info_handler(csm);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
mlacp_sync_req->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -474,6 +580,13 @@ static void mlacp_sync_recv_portChanInfo(struct CSM* csm, struct Msg* msg)
|
||||
if (mlacp_fsm_update_port_channel_info(csm, portconf) == MCLAG_ERROR)
|
||||
{
|
||||
mlacp_sync_send_nak_handler(csm, msg);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
|
||||
}
|
||||
else
|
||||
{
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
portconf->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -485,6 +598,8 @@ static void mlacp_sync_recv_peerLlinkInfo(struct CSM* csm, struct Msg* msg)
|
||||
|
||||
peerlink = (mLACPPeerLinkInfoTLV*)&(msg->buf[sizeof(ICCHdr)]);
|
||||
mlacp_fsm_update_peerlink_info( csm, peerlink);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
peerlink->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -495,6 +610,8 @@ static void mlacp_sync_recv_macInfo(struct CSM* csm, struct Msg* msg)
|
||||
|
||||
mac_info = (struct mLACPMACInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
|
||||
mlacp_fsm_update_mac_info_from_peer(csm, mac_info);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
mac_info->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -505,6 +622,8 @@ static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg)
|
||||
|
||||
arp_info = (struct mLACPARPInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
|
||||
mlacp_fsm_update_arp_info(csm, arp_info);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
arp_info->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -518,6 +637,7 @@ static void mlacp_sync_recv_ndiscInfo(struct CSM *csm, struct Msg *msg)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg)
|
||||
{
|
||||
/*Don't support currently*/
|
||||
@ -530,6 +650,8 @@ static void mlacp_sync_recv_heartbeat(struct CSM* csm, struct Msg* msg)
|
||||
|
||||
tlv = (struct mLACPHeartbeatTLV *)(&msg->buf[sizeof(ICCHdr)]);
|
||||
mlacp_fsm_update_heartbeat(csm, tlv);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -540,10 +662,102 @@ static void mlacp_sync_recv_warmboot(struct CSM* csm, struct Msg* msg)
|
||||
|
||||
tlv = (struct mLACPWarmbootTLV *)(&msg->buf[sizeof(ICCHdr)]);
|
||||
mlacp_fsm_update_warmboot(csm, tlv);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void mlacp_fsm_recv_if_up_ack(struct CSM* csm, struct Msg* msg)
|
||||
{
|
||||
struct mLACPIfUpAckTLV *tlv = NULL;
|
||||
struct LocalInterface *local_if = NULL;
|
||||
uint16_t if_id;
|
||||
|
||||
tlv = (struct mLACPIfUpAckTLV *)(&msg->buf[sizeof(ICCHdr)]);
|
||||
if (tlv == NULL)
|
||||
return;
|
||||
|
||||
if_id = ntohs(tlv->if_id);
|
||||
|
||||
if (tlv->if_type == IF_UP_ACK_TYPE_PORT_CHANNEL)
|
||||
{
|
||||
local_if = local_if_find_by_po_id(if_id);
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM",
|
||||
"RX if_up_ack: po_id %d, local if 0x%x, active %u",
|
||||
if_id, local_if, local_if ? local_if->po_active : 0);
|
||||
|
||||
/* Ignore the ack if MLAG interface has gone down */
|
||||
if (local_if && local_if->po_active)
|
||||
mlacp_link_enable_traffic_distribution(local_if);
|
||||
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_ERR("ICCP_FSM", "RX if_up_ack: invalid i/f type %u, i/f ID %u",
|
||||
tlv->if_type, if_id);
|
||||
MLACP_SET_ICCP_RX_DBG_COUNTER(csm,
|
||||
tlv->icc_parameter.type, ICCP_DBG_CNTR_STS_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
void mlacp_local_lif_state_mac_handler(struct CSM* csm)
|
||||
{
|
||||
struct LocalInterface* local_if = NULL;
|
||||
|
||||
LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
if ((local_if->state == PORT_STATE_DOWN) && (local_if->type == IF_T_PORT_CHANNEL))
|
||||
{
|
||||
// clear the pending macs if timer is expired.
|
||||
if (local_if->po_down_time && ((time(NULL) - local_if->po_down_time) > MLACP_LOCAL_IF_DOWN_TIMER))
|
||||
{
|
||||
mlacp_local_lif_clear_pending_mac(csm, local_if);
|
||||
local_if->po_down_time = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mlacp_peer_link_learning_handler(struct CSM* csm)
|
||||
{
|
||||
if (csm->peer_link_if == NULL)
|
||||
return;
|
||||
|
||||
if (csm->peer_link_if->vlan_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (csm->peer_link_learning_retry_time && ((time(NULL) - csm->peer_link_learning_retry_time) > 2))
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "peer_link_learning_enable %d", csm->peer_link_learning_enable);
|
||||
set_peerlink_learn_kernel(csm, csm->peer_link_learning_enable, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void mlacp_mac_msg_queue_reinit(struct CSM* csm)
|
||||
{
|
||||
|
||||
struct MACMsg* mac_msg = NULL;
|
||||
|
||||
MLACP_MAC_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
|
||||
|
||||
ICCPD_LOG_NOTICE("ICCP_FDB", "mlacp_mac_msg_queue_reinit clear mac_msg_list pointers in existing MAC entries");
|
||||
|
||||
// unset the mac_msg_list pointers for existing MAC entries.
|
||||
RB_FOREACH (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb)
|
||||
{
|
||||
if (MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
|
||||
{
|
||||
CLEAR_MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* MLACP Init
|
||||
*
|
||||
@ -563,7 +777,8 @@ void mlacp_init(struct CSM* csm, int all)
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
|
||||
mlacp_mac_msg_queue_reinit(csm);
|
||||
|
||||
PIF_QUEUE_REINIT(MLACP(csm).pif_list);
|
||||
LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list);
|
||||
|
||||
@ -572,7 +787,7 @@ void mlacp_init(struct CSM* csm, int all)
|
||||
/* if no clean all, keep the arp info & local interface info for next connection*/
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list);
|
||||
RB_INIT(mac_rb_tree, &MLACP(csm).mac_rb );
|
||||
LIF_QUEUE_REINIT(MLACP(csm).lif_list);
|
||||
|
||||
MLACP(csm).node_id = MLACP_SYSCONF_NODEID_MSB_MASK;
|
||||
@ -596,10 +811,11 @@ void mlacp_finalize(struct CSM* csm)
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
|
||||
mlacp_mac_msg_queue_reinit(csm);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list);
|
||||
|
||||
RB_INIT(mac_rb_tree, &MLACP(csm).mac_rb );
|
||||
|
||||
/* remove lif & lif-purge queue */
|
||||
LIF_QUEUE_REINIT(MLACP(csm).lif_list);
|
||||
@ -637,8 +853,14 @@ void mlacp_fsm_transit(struct CSM* csm)
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mlacp_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).arp_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_msg_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_msg_list);
|
||||
mlacp_mac_msg_queue_reinit(csm);
|
||||
MLACP(csm).current_state = MLACP_STATE_INIT;
|
||||
if (csm->sock_fd > 0)
|
||||
{
|
||||
/* Close CSM socket and reset its value */
|
||||
scheduler_csm_socket_cleanup(csm, 2);
|
||||
SYSTEM_INCR_SOCKET_CLEANUP_COUNTER(system_get_instance());
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -657,6 +879,9 @@ void mlacp_fsm_transit(struct CSM* csm)
|
||||
|
||||
mlacp_sync_send_heartbeat(csm);
|
||||
|
||||
mlacp_local_lif_state_mac_handler(csm);
|
||||
mlacp_peer_link_learning_handler(csm);
|
||||
|
||||
/* Dequeue msg if any*/
|
||||
while (have_msg)
|
||||
{
|
||||
@ -728,7 +953,7 @@ void mlacp_fsm_transit(struct CSM* csm)
|
||||
}
|
||||
|
||||
/* Helper function for dumping application state machine */
|
||||
static char* mlacp_state(struct CSM* csm)
|
||||
char* mlacp_state(struct CSM* csm)
|
||||
{
|
||||
if (csm == NULL )
|
||||
return "MLACP_NULL";
|
||||
@ -767,12 +992,6 @@ void mlacp_enqueue_msg(struct CSM* csm, struct Msg* msg)
|
||||
if (msg == NULL )
|
||||
return;
|
||||
|
||||
#if 0
|
||||
icc_hdr = (ICCHdr*)msg->buf;
|
||||
icc_param = (ICCParameter*)&msg->buf[sizeof(ICCHdr)];
|
||||
ICCPD_LOG_DEBUG("mlacp_fsm", " mLACP enqueue: tlv = 0x%04x", icc_param->type);
|
||||
#endif
|
||||
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).mlacp_msg_list), msg, tail);
|
||||
|
||||
return;
|
||||
@ -792,32 +1011,77 @@ struct Msg* mlacp_dequeue_msg(struct CSM* csm)
|
||||
return msg;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* When peerlink ready, prepare the MACMsg
|
||||
*
|
||||
******************************************/
|
||||
static void mlacp_resync_mac(struct CSM* csm)
|
||||
void mlacp_sync_mac(struct CSM* csm)
|
||||
{
|
||||
struct Msg* msg = NULL;
|
||||
struct MACMsg* mac_msg = NULL;
|
||||
struct Msg *msg_send = NULL;
|
||||
|
||||
/* recover MAC info sync from peer*/
|
||||
if (!TAILQ_EMPTY(&(MLACP(csm).mac_list)))
|
||||
RB_FOREACH (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb)
|
||||
{
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).mac_list, tail)
|
||||
/*If MAC with local age flag, dont sync to peer. Such MAC only exist when peer is warm-reboot.
|
||||
If peer is warm-reboot, peer age flag is not set when connection is lost.
|
||||
When MAC is aged in local switch, this MAC is not deleted for no peer age flag.
|
||||
After warm-reboot, this MAC must be learnt by peer and sync to local switch*/
|
||||
if (!(mac_msg->age_flag & MAC_AGE_LOCAL))
|
||||
{
|
||||
mac_msg = (struct MACMsg*)msg->buf;
|
||||
mac_msg->op_type = MAC_SYNC_ADD;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0)
|
||||
//As part of local sync do not delete peer age
|
||||
//mac_msg->age_flag &= ~MAC_AGE_PEER;
|
||||
|
||||
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
|
||||
{
|
||||
mac_msg->age_flag &= ~MAC_AGE_PEER;
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "MAC-msg-list enqueue: %s, add %s vlan-id %d, age_flag %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->age_flag);
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), mac_msg, tail);
|
||||
}
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FDB", "Sync MAC: MAC-msg-list enqueue interface %s, "
|
||||
"MAC %s vlan %d, age_flag %d", mac_msg->ifname,
|
||||
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->age_flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*If MAC with local age flag and is point to MCLAG enabled port, reomove local age flag*/
|
||||
if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG("ICCP_FDB", "Sync MAC: MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, age_flag %d",
|
||||
mac_msg->ifname, mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->age_flag);
|
||||
/* After warmboot remote mac can exist, should not
|
||||
update existing flag
|
||||
*/
|
||||
//mac_msg->age_flag &= ~MAC_AGE_LOCAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void mlacp_local_lif_clear_pending_mac(struct CSM* csm, struct LocalInterface *local_lif)
|
||||
{
|
||||
ICCPD_LOG_DEBUG("ICCP_FDB", "mlacp_local_lif_clear_pending_mac If: %s ", local_lif->name );
|
||||
struct MACMsg* mac_msg = NULL, *mac_temp = NULL;
|
||||
RB_FOREACH_SAFE (mac_msg, mac_rb_tree, &MLACP(csm).mac_rb, mac_temp)
|
||||
{
|
||||
if (mac_msg->pending_local_del && strcmp(mac_msg->origin_ifname, local_lif->name) == 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG("ICCP_FDB", "Clear pending MAC: MAC-msg-list not enqueue for local age flag: %s, mac %s vlan-id %d, age_flag %d, remove local age flag",
|
||||
mac_msg->ifname, mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->age_flag);
|
||||
|
||||
del_mac_from_chip(mac_msg);
|
||||
|
||||
// if static dont delete mac
|
||||
if (mac_msg->fdb_type != MAC_TYPE_STATIC)
|
||||
{
|
||||
//TBD do we need to send delete notification to peer .?
|
||||
MAC_RB_REMOVE(mac_rb_tree, &MLACP(csm).mac_rb, mac_msg);
|
||||
|
||||
mac_msg->op_type = MAC_SYNC_DEL;
|
||||
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
|
||||
{
|
||||
free(mac_msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
mac_msg->pending_local_del = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************
|
||||
@ -837,6 +1101,7 @@ static void mlacp_resync_arp(struct CSM* csm)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
arp_msg->op_type = NEIGH_SYNC_ADD;
|
||||
arp_msg->flag = 0;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail);
|
||||
@ -862,6 +1127,7 @@ static void mlacp_resync_ndisc(struct CSM *csm)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
ndisc_msg->op_type = NEIGH_SYNC_ADD;
|
||||
ndisc_msg->flag = 0;
|
||||
if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, sizeof(struct NDISCMsg)) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail);
|
||||
@ -1016,6 +1282,15 @@ static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg)
|
||||
case TLV_T_MLACP_WARMBOOT_FLAG:
|
||||
mlacp_sync_recv_warmboot(csm, msg);
|
||||
break;
|
||||
|
||||
case TLV_T_MLACP_IF_UP_ACK:
|
||||
mlacp_fsm_recv_if_up_ack(csm, msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
ICCPD_LOG_ERR("ICCP_FSM", "Receive unsupported msg 0x%x from peer",
|
||||
icc_param->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/*ICCPD_LOG_DEBUG("mlacp_fsm", " [Sync Recv] %s... DONE", get_tlv_type_string(icc_param->type));*/
|
||||
@ -1238,7 +1513,13 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
|
||||
iccp_csm_send(csm, g_csm_buf, len);
|
||||
/* Destroy old interface*/
|
||||
if (lif_purge != NULL)
|
||||
{
|
||||
/* Re-enable traffic distribution on MCLAG interface */
|
||||
if ((lif_purge->type == IF_T_PORT_CHANNEL) && lif_purge->is_traffic_disable)
|
||||
mlacp_link_enable_traffic_distribution(lif_purge);
|
||||
|
||||
LIST_REMOVE(lif_purge, mlacp_purge_next);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send mlag lif*/
|
||||
@ -1246,6 +1527,10 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
|
||||
{
|
||||
if (lif->type == IF_T_PORT_CHANNEL && lif->port_config_sync)
|
||||
{
|
||||
/* Disable traffic distribution on LAG members if LAG is down */
|
||||
if (!lif->po_active)
|
||||
mlacp_link_disable_traffic_distribution(lif);
|
||||
|
||||
/* Send port channel information*/
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
len = mlacp_prepare_for_Aggport_config(csm, g_csm_buf, CSM_BUFFER_SIZE, lif, 0);
|
||||
@ -1264,8 +1549,12 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
|
||||
/* Send port channel state information*/
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
len = mlacp_prepare_for_Aggport_state(csm, g_csm_buf, CSM_BUFFER_SIZE, lif);
|
||||
iccp_csm_send(csm, g_csm_buf, len);
|
||||
lif->changed = 0;
|
||||
//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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1291,3 +1580,90 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Interface up ACK
|
||||
*
|
||||
****************************************/
|
||||
static void mlacp_fsm_send_if_up_ack(
|
||||
struct CSM *csm,
|
||||
uint8_t if_type,
|
||||
uint16_t if_id,
|
||||
uint8_t port_isolation_enable)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
int msg_len = 0;
|
||||
int rc = -10;
|
||||
|
||||
sys = system_get_instance();
|
||||
if (sys == NULL)
|
||||
return;
|
||||
|
||||
/* Interface up ACK is expected only after the interface is up */
|
||||
if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE)
|
||||
return;
|
||||
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
msg_len = mlacp_prepare_for_if_up_ack(
|
||||
csm, g_csm_buf, CSM_BUFFER_SIZE, if_type, if_id, port_isolation_enable);
|
||||
if (msg_len > 0)
|
||||
rc = iccp_csm_send(csm, g_csm_buf, msg_len);
|
||||
|
||||
if (rc <= 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "failed, interface type/id %d/%d, rc %d",
|
||||
if_type, if_id, rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__,"interface type/id %d/%d", if_type, if_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* MLACP ICCP mesage type to debug counter type conversion */
|
||||
ICCP_DBG_CNTR_MSG_e mlacp_fsm_iccp_to_dbg_msg_type(uint32_t tlv_type)
|
||||
{
|
||||
switch (tlv_type)
|
||||
{
|
||||
case TLV_T_MLACP_SYSTEM_CONFIG:
|
||||
return ICCP_DBG_CNTR_MSG_SYS_CONFIG;
|
||||
|
||||
case TLV_T_MLACP_AGGREGATOR_CONFIG:
|
||||
return ICCP_DBG_CNTR_MSG_AGGR_CONFIG;
|
||||
|
||||
case TLV_T_MLACP_AGGREGATOR_STATE:
|
||||
return ICCP_DBG_CNTR_MSG_AGGR_STATE;
|
||||
|
||||
case TLV_T_MLACP_SYNC_REQUEST:
|
||||
return ICCP_DBG_CNTR_MSG_SYNC_REQ;
|
||||
|
||||
case TLV_T_MLACP_SYNC_DATA:
|
||||
return ICCP_DBG_CNTR_MSG_SYNC_DATA;
|
||||
|
||||
case TLV_T_MLACP_HEARTBEAT:
|
||||
return ICCP_DBG_CNTR_MSG_HEART_BEAT;
|
||||
|
||||
case TLV_T_MLACP_PORT_CHANNEL_INFO:
|
||||
return ICCP_DBG_CNTR_MSG_PORTCHANNEL_INFO;
|
||||
|
||||
case TLV_T_MLACP_PEERLINK_INFO:
|
||||
return ICCP_DBG_CNTR_MSG_PEER_LINK_INFO;
|
||||
|
||||
case TLV_T_MLACP_ARP_INFO:
|
||||
return ICCP_DBG_CNTR_MSG_ARP_INFO;
|
||||
|
||||
case TLV_T_MLACP_MAC_INFO:
|
||||
return ICCP_DBG_CNTR_MSG_MAC_INFO;
|
||||
|
||||
case TLV_T_MLACP_WARMBOOT_FLAG:
|
||||
return ICCP_DBG_CNTR_MSG_WARM_BOOT;
|
||||
|
||||
case TLV_T_MLACP_IF_UP_ACK:
|
||||
return ICCP_DBG_CNTR_MSG_IF_UP_ACK;
|
||||
|
||||
default:
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "No debug counter for TLV type %u",
|
||||
tlv_type);
|
||||
return ICCP_DBG_CNTR_MSG_MAX;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -91,6 +91,10 @@ int mlacp_prepare_for_sync_request_tlv(struct CSM* csm, char* buf, size_t max_bu
|
||||
tlv->port_num_agg_id = 0;
|
||||
tlv->actor_key = 0;
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX sync_request: role %s, sync_state %s",
|
||||
(csm->role_type == STP_ROLE_STANDBY) ? "standby" : "active",
|
||||
mlacp_state(csm));
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -138,6 +142,7 @@ int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_s
|
||||
else
|
||||
tlv->flags = htons(0x01);
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_CSM", "TX sync %s", end ? "end" : "start");
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -182,6 +187,10 @@ int mlacp_prepare_for_sys_config(struct CSM* csm, char* buf, size_t max_buf_size
|
||||
memcpy(tlv->sys_id, MLACP(csm).system_id, ETHER_ADDR_LEN);
|
||||
tlv->sys_priority = htons(MLACP(csm).system_priority);
|
||||
tlv->node_id = MLACP(csm).node_id;
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX sys_config: systemID %s, priority %u, nodeID %u",
|
||||
mac_addr_to_str(MLACP(csm).system_id), MLACP(csm).system_priority,
|
||||
MLACP(csm).node_id);
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -232,6 +241,8 @@ int mlacp_prepare_for_Aggport_state(struct CSM* csm, char* buf, size_t max_buf_s
|
||||
tlv->actor_key = 0;
|
||||
tlv->agg_state = local_if->state;
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX aggrport_state: %s is %s",
|
||||
local_if->name, (local_if->state == PORT_STATE_UP) ? "up" : "down");
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -280,6 +291,8 @@ int mlacp_prepare_for_Aggport_config(struct CSM* csm,
|
||||
memcpy(tlv->agg_name, lif->name, MAX_L_PORT_NAME);
|
||||
memcpy(tlv->mac_addr, lif->mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX aggrport_config: %s, purge_flag %d, mac %s",
|
||||
lif->name, purge_flag, mac_addr_to_str(lif->mac_addr));
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -322,12 +335,13 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu
|
||||
|
||||
MacData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPMACInfoTLV) + sizeof(struct mLACPMACData) * count];
|
||||
MacData->type = mac_msg->op_type;
|
||||
sprintf(MacData->mac_str, "%s", mac_msg->mac_str);
|
||||
MacData->mac_type = mac_msg->fdb_type;
|
||||
memcpy(MacData->mac_addr, mac_msg->mac_addr,ETHER_ADDR_LEN);
|
||||
sprintf(MacData->ifname, "%s", mac_msg->origin_ifname);
|
||||
MacData->vid = htons(mac_msg->vid);
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname,
|
||||
mac_msg->mac_str, mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count);
|
||||
ICCPD_LOG_DEBUG("ICCP_FDB", "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname,
|
||||
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->op_type == MAC_SYNC_ADD ? "add" : "del", count);
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
@ -336,7 +350,7 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu
|
||||
* Preprare Sync ARP-Info TLV
|
||||
*
|
||||
* ***************************************/
|
||||
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count)
|
||||
int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size, struct ARPMsg* arp_msg, int count, int dir)
|
||||
{
|
||||
struct mLACPARPInfoTLV* tlv = NULL;
|
||||
size_t msg_len = 0;
|
||||
@ -373,13 +387,15 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size,
|
||||
ArpData = (struct ARPMsg *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPARPInfoTLV) + sizeof(struct ARPMsg) * count];
|
||||
|
||||
ArpData->op_type = arp_msg->op_type;
|
||||
ArpData->flag = arp_msg->flag;
|
||||
sprintf(ArpData->ifname, "%s", arp_msg->ifname);
|
||||
ArpData->ipv4_addr = arp_msg->ipv4_addr;
|
||||
memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send ARP messge to peer, if name %s mac %02x:%02x:%02x:%02x:%02x:%02x IP %s", ArpData->ifname, ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2],
|
||||
ArpData->mac_addr[3], ArpData->mac_addr[4], ArpData->mac_addr[5], show_ip_str(ArpData->ipv4_addr));
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send ARP messge to peer, dir %d, flag %d, if name %s mac %02x:%02x:%02x:%02x:%02x:%02x IP %s",
|
||||
dir, ArpData->flag, ArpData->ifname,
|
||||
ArpData->mac_addr[0], ArpData->mac_addr[1], ArpData->mac_addr[2], ArpData->mac_addr[3], ArpData->mac_addr[4],
|
||||
ArpData->mac_addr[5], show_ip_str(ArpData->ipv4_addr));
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -387,14 +403,13 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size,
|
||||
* Preprare Sync NDISC-Info TLV
|
||||
*
|
||||
* ***************************************/
|
||||
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count)
|
||||
int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size, struct NDISCMsg *ndisc_msg, int count, int dir)
|
||||
{
|
||||
|
||||
struct mLACPNDISCInfoTLV *tlv = NULL;
|
||||
size_t msg_len = 0;
|
||||
size_t tlv_len = 0;
|
||||
ICCHdr *icc_hdr = NULL;
|
||||
struct NDISCMsg *NdiscData;
|
||||
struct NDISCMsg *NdiscData = NULL;
|
||||
|
||||
if (!csm)
|
||||
return -1;
|
||||
@ -422,14 +437,16 @@ int mlacp_prepare_for_ndisc_info(struct CSM *csm, char *buf, size_t max_buf_size
|
||||
tlv->icc_parameter.type = htons(TLV_T_MLACP_NDISC_INFO);
|
||||
}
|
||||
|
||||
NdiscData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * count];
|
||||
NdiscData = (struct NDISCMsg *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * count];
|
||||
|
||||
NdiscData->op_type = ndisc_msg->op_type;
|
||||
NdiscData->flag = ndisc_msg->flag;
|
||||
sprintf(NdiscData->ifname, "%s", ndisc_msg->ifname);
|
||||
memcpy(NdiscData->ipv6_addr, ndisc_msg->ipv6_addr, 32);
|
||||
memcpy(NdiscData->ipv6_addr, ndisc_msg->ipv6_addr, 16);
|
||||
memcpy(NdiscData->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send ND messge to peer, if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x IPv6 %s", NdiscData->ifname,
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send ND messge to peer, dir %d, flag %d, if name %s mac =%02x:%02x:%02x:%02x:%02x:%02x IPv6 %s",
|
||||
dir, NdiscData->flag, NdiscData->ifname,
|
||||
NdiscData->mac_addr[0], NdiscData->mac_addr[1], NdiscData->mac_addr[2], NdiscData->mac_addr[3], NdiscData->mac_addr[4],
|
||||
NdiscData->mac_addr[5], show_ipv6_str((char *)NdiscData->ipv6_addr));
|
||||
|
||||
@ -465,9 +482,9 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf,
|
||||
return MCLAG_ERROR;
|
||||
|
||||
/* Calculate VLAN ID Length */
|
||||
LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next)
|
||||
if (vlan_id != NULL)
|
||||
num_of_vlan_id++;
|
||||
RB_FOREACH(vlan_id, vlan_rb_tree, &(port_channel->vlan_tree))
|
||||
if (vlan_id != NULL)
|
||||
num_of_vlan_id++;
|
||||
|
||||
tlv_len = sizeof(struct mLACPPortChannelInfoTLV) + sizeof(struct mLACPVLANData) * num_of_vlan_id;
|
||||
|
||||
@ -500,7 +517,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf,
|
||||
tlv->num_of_vlan_id = htons(num_of_vlan_id);
|
||||
|
||||
num_of_vlan_id = 0;
|
||||
LIST_FOREACH(vlan_id, &(port_channel->vlan_list), port_next)
|
||||
RB_FOREACH(vlan_id, vlan_rb_tree, &(port_channel->vlan_tree))
|
||||
{
|
||||
if (vlan_id != NULL )
|
||||
{
|
||||
@ -512,7 +529,7 @@ int mlacp_prepare_for_port_channel_info(struct CSM* csm, char* buf,
|
||||
}
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "PortChannel%d: ipv4 addr = %s l3 mode %d", port_channel->po_id, show_ip_str( tlv->ipv4_addr), tlv->l3_mode);
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX po_info: %s has %d vlans", port_channel->name, num_of_vlan_id);
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -562,8 +579,8 @@ int mlacp_prepare_for_port_peerlink_info(struct CSM* csm, char* buf,
|
||||
memcpy(tlv->if_name, peerlink_port->name, MAX_L_PORT_NAME);
|
||||
tlv->port_type = peerlink_port->type;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port is %s, type = %d", tlv->if_name, tlv->port_type);
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX peerlink_info: name %s, type %d",
|
||||
peerlink_port->name, peerlink_port->type);
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
@ -649,8 +666,60 @@ int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_siz
|
||||
|
||||
tlv->icc_parameter.len = htons(sizeof(struct mLACPWarmbootTLV) - sizeof(ICCParameter));
|
||||
tlv->warmboot = 0x1;
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX start warm reboot");
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send warm reboot notification to peer!");
|
||||
/*****************************************
|
||||
* Prepare interface up ACK message
|
||||
*
|
||||
* ***************************************/
|
||||
int mlacp_prepare_for_if_up_ack(
|
||||
struct CSM *csm,
|
||||
char *buf,
|
||||
size_t max_buf_size,
|
||||
uint8_t if_type,
|
||||
uint16_t if_id,
|
||||
uint8_t port_isolation_state)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
ICCHdr* icc_hdr = (ICCHdr*) buf;
|
||||
struct mLACPIfUpAckTLV* tlv = (struct mLACPIfUpAckTLV*) &buf[sizeof(ICCHdr)];
|
||||
size_t msg_len = sizeof(ICCHdr) + sizeof(struct mLACPIfUpAckTLV);
|
||||
|
||||
if(csm == NULL)
|
||||
return -1;
|
||||
|
||||
if(buf == NULL)
|
||||
return -1;
|
||||
|
||||
if(msg_len > max_buf_size)
|
||||
return -1;
|
||||
|
||||
if((sys = system_get_instance()) == NULL)
|
||||
return -1;
|
||||
|
||||
/* Prepare for sync request */
|
||||
memset(buf, 0, max_buf_size);
|
||||
|
||||
icc_hdr = (ICCHdr*) buf;
|
||||
tlv = (struct mLACPIfUpAckTLV*) &buf[sizeof(ICCHdr)];
|
||||
|
||||
/* ICC header */
|
||||
mlacp_fill_icc_header(csm, icc_hdr, msg_len);
|
||||
|
||||
/* If up ack TLV */
|
||||
tlv->icc_parameter.u_bit = 0;
|
||||
tlv->icc_parameter.f_bit = 0;
|
||||
tlv->icc_parameter.type = htons(TLV_T_MLACP_IF_UP_ACK);
|
||||
|
||||
tlv->icc_parameter.len = htons(sizeof(struct mLACPIfUpAckTLV) - sizeof(ICCParameter));
|
||||
tlv->if_type = if_type;
|
||||
tlv->if_id = htons(if_id);
|
||||
tlv->port_isolation_state = port_isolation_state;
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "TX if_up_ack: PortChannel%d, isolation_set %d",
|
||||
if_id, port_isolation_state);
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
618
src/iccpd/src/openbsd_tree.c
Normal file
618
src/iccpd/src/openbsd_tree.c
Normal 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);
|
||||
}
|
@ -28,8 +28,23 @@
|
||||
#include "../include/port.h"
|
||||
#include "../include/system.h"
|
||||
#include "../include/iccp_csm.h"
|
||||
#include "../include/iccp_netlink.h"
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
#include "../include/scheduler.h"
|
||||
#include "../include/iccp_netlink.h"
|
||||
#include "../include/iccp_ifm.h"
|
||||
|
||||
|
||||
static int vlan_node_compare(const struct VLAN_ID *p_vlan_node1, const struct VLAN_ID *p_vlan_node2)
|
||||
{
|
||||
if (p_vlan_node1->vid < p_vlan_node2->vid)
|
||||
return -1;
|
||||
|
||||
if (p_vlan_node1->vid > p_vlan_node2->vid)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
RB_GENERATE(vlan_rb_tree, VLAN_ID, vlan_entry, vlan_node_compare);
|
||||
|
||||
void local_if_init(struct LocalInterface* local_if)
|
||||
{
|
||||
@ -46,11 +61,14 @@ void local_if_init(struct LocalInterface* local_if)
|
||||
local_if->is_peer_link = 0;
|
||||
local_if->is_arp_accept = 0;
|
||||
local_if->l3_mode = 0;
|
||||
local_if->master_ifindex = 0;
|
||||
local_if->state = PORT_STATE_DOWN;
|
||||
local_if->prefixlen = 32;
|
||||
local_if->csm = NULL;
|
||||
local_if->isolate_to_peer_link = 0;
|
||||
LIST_INIT(&local_if->vlan_list);
|
||||
local_if->is_l3_proto_enabled = false;
|
||||
local_if->vlan_count = 0;
|
||||
RB_INIT(vlan_rb_tree, &local_if->vlan_tree);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -64,7 +82,7 @@ void vlan_info_init(struct VLAN_ID* vlan)
|
||||
return;
|
||||
}
|
||||
|
||||
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
struct LocalInterface* local_if_create(int ifindex, char* ifname, int type, uint8_t state)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
struct LocalInterface* local_if = NULL;
|
||||
@ -77,11 +95,10 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
if (!(sys = system_get_instance()))
|
||||
return NULL;
|
||||
|
||||
if (ifindex < 0)
|
||||
return NULL;
|
||||
|
||||
if ((local_if = local_if_find_by_ifindex(ifindex)))
|
||||
return local_if;
|
||||
if (ifindex > 0) {
|
||||
if ((local_if = local_if_find_by_ifindex(ifindex)))
|
||||
return local_if;
|
||||
}
|
||||
|
||||
if (!(local_if = (struct LocalInterface*)malloc(sizeof(struct LocalInterface))))
|
||||
{
|
||||
@ -91,7 +108,10 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
|
||||
local_if_init(local_if);
|
||||
local_if->ifindex = ifindex;
|
||||
local_if->type = type;
|
||||
local_if->type = type;
|
||||
local_if->state = state;
|
||||
|
||||
local_if->po_down_time = 0;
|
||||
|
||||
if (local_if->type == IF_T_PORT_CHANNEL)
|
||||
{
|
||||
@ -107,6 +127,7 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
return NULL;
|
||||
|
||||
local_if->po_id = atoi(&ifname[i]);
|
||||
local_if->po_active = (state == PORT_STATE_UP) ? 1 : 0;
|
||||
}
|
||||
|
||||
if (ifname)
|
||||
@ -121,7 +142,10 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
break;
|
||||
|
||||
case IF_T_VLAN:
|
||||
/* do nothing currently. */
|
||||
if(is_unique_ip_configured(local_if->name))
|
||||
{
|
||||
local_if->is_l3_proto_enabled = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IF_T_VXLAN:
|
||||
@ -142,6 +166,9 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
|
||||
LIST_INSERT_HEAD(&(sys->lif_list), local_if, system_next);
|
||||
|
||||
//if there is pending vlan membership for this interface move to system lif
|
||||
move_pending_vlan_mbr_to_lif(sys, local_if);
|
||||
|
||||
/*Check the intf is peer-link? Only support PortChannel and Ethernet currently*/
|
||||
/*When set peer-link, the local-if is probably not created*/
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
@ -150,6 +177,7 @@ struct LocalInterface* local_if_create(int ifindex, char* ifname, int type)
|
||||
{
|
||||
local_if->is_peer_link = 1;
|
||||
csm->peer_link_if = local_if;
|
||||
set_peerlink_learn_kernel(csm, 0, 3);
|
||||
break;
|
||||
}
|
||||
/*check the intf is bind with csm*/
|
||||
@ -217,24 +245,40 @@ struct LocalInterface* local_if_find_by_po_id(int po_id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void local_if_vlan_remove(struct LocalInterface *lif_vlan)
|
||||
void local_if_vlan_remove(struct LocalInterface *lif_vlan)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct LocalInterface *lif = NULL;
|
||||
struct VLAN_ID *vlan = NULL;
|
||||
int vid = 0;
|
||||
struct VLAN_ID vlan_key = { 0 };
|
||||
|
||||
if (!lif_vlan || lif_vlan->type != IF_T_VLAN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sscanf(lif_vlan->name, "Vlan%d", &vid);
|
||||
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
|
||||
vlan_key.vid = vid;
|
||||
|
||||
|
||||
if ((sys = system_get_instance()) != NULL)
|
||||
{
|
||||
LIST_FOREACH(lif, &(sys->lif_list), system_next)
|
||||
{
|
||||
LIST_FOREACH(vlan, &(lif->vlan_list), port_next)
|
||||
{
|
||||
if (lif_vlan != vlan->vlan_itf)
|
||||
continue;
|
||||
if (lif->type == IF_T_VLAN)
|
||||
continue;
|
||||
|
||||
//delink this vlan (lif_vlan) interface from all associated lifs
|
||||
//in scenario where vlan membership delete comes later when compared
|
||||
//to vlan interface delete from kernel
|
||||
vlan = RB_FIND(vlan_rb_tree, &(lif->vlan_tree), &vlan_key);
|
||||
if (vlan)
|
||||
{
|
||||
vlan->vlan_itf = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@ -279,6 +323,7 @@ void local_if_destroy(char *ifname)
|
||||
{
|
||||
struct LocalInterface* lif = NULL;
|
||||
struct CSM *csm = NULL;
|
||||
struct CSM *peer_ifname_csm = NULL;
|
||||
struct System *sys = NULL;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
@ -297,21 +342,27 @@ void local_if_destroy(char *ifname)
|
||||
else
|
||||
local_if_remove(lif);
|
||||
|
||||
csm = lif->csm;
|
||||
if (csm && csm->peer_link_if && strcmp(csm->peer_link_if->name, ifname) == 0)
|
||||
//handle peer_link del case
|
||||
if ( (peer_ifname_csm = system_get_csm_by_peer_ifname(ifname)) != NULL )
|
||||
{
|
||||
/*if the peerlink interface is not created, peer connection can not establish*/
|
||||
scheduler_session_disconnect_handler(csm);
|
||||
scheduler_session_disconnect_handler(peer_ifname_csm);
|
||||
|
||||
// The function above calls iccp_csm_status_reset, which sets csm->Peer_link_if to NULL,
|
||||
// accessing the peer_link_if cause crash due to null pointer access.
|
||||
#if 0
|
||||
csm->peer_link_if->is_peer_link = 0;
|
||||
csm->peer_link_if = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
csm = lif->csm;
|
||||
if (csm && MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
goto to_mlacp_purge;
|
||||
else
|
||||
goto to_sys_purge;
|
||||
|
||||
to_sys_purge:
|
||||
to_sys_purge:
|
||||
/* sys purge */
|
||||
LIST_REMOVE(lif, system_next);
|
||||
if (lif->csm)
|
||||
@ -319,7 +370,7 @@ void local_if_destroy(char *ifname)
|
||||
LIST_INSERT_HEAD(&(sys->lif_purge_list), lif, system_purge_next);
|
||||
return;
|
||||
|
||||
to_mlacp_purge:
|
||||
to_mlacp_purge:
|
||||
/* sys & mlacp purge */
|
||||
LIST_REMOVE(lif, system_next);
|
||||
LIST_REMOVE(lif, mlacp_next);
|
||||
@ -336,8 +387,11 @@ int local_if_is_l3_mode(struct LocalInterface* local_if)
|
||||
if (local_if == NULL)
|
||||
return 0;
|
||||
|
||||
if (local_if->ipv4_addr != 0 || memcmp(local_if->ipv6_addr, addr_null, 16) != 0)
|
||||
if ((local_if->ipv4_addr != 0)
|
||||
|| (memcmp(local_if->ipv6_addr, addr_null, 16) != 0)
|
||||
|| (local_if->master_ifindex != 0)) {
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -361,6 +415,25 @@ void local_if_change_flag_clear(void)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void local_if_mlacp_purge_del(struct LocalInterface* lif)
|
||||
{
|
||||
struct CSM* csm;
|
||||
struct LocalInterface *lif_purge;
|
||||
|
||||
if (lif && lif->csm)
|
||||
{
|
||||
LIST_FOREACH(lif_purge, &(MLACP(lif->csm).lif_purge_list), mlacp_purge_next)
|
||||
{
|
||||
if (lif_purge == lif)
|
||||
{
|
||||
LIST_REMOVE(lif, mlacp_purge_next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void local_if_purge_clear(void)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
@ -375,8 +448,7 @@ void local_if_purge_clear(void)
|
||||
lif = LIST_FIRST(&(sys->lif_purge_list));
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Purge %s", lif->name);
|
||||
LIST_REMOVE(lif, system_purge_next);
|
||||
if (lif->mlacp_purge_next.le_next != 0 && lif->mlacp_purge_next.le_prev != 0)
|
||||
LIST_REMOVE(lif, mlacp_purge_next);
|
||||
local_if_mlacp_purge_del(lif);
|
||||
local_if_del_all_vlan(lif);
|
||||
free(lif);
|
||||
}
|
||||
@ -470,17 +542,15 @@ struct PeerInterface* peer_if_find_by_name(struct CSM* csm, char* name)
|
||||
|
||||
void peer_if_del_all_vlan(struct PeerInterface* pif)
|
||||
{
|
||||
struct VLAN_ID *pvlan = NULL;
|
||||
struct VLAN_ID *vlan = NULL;
|
||||
struct VLAN_ID* vlan_temp = NULL;
|
||||
|
||||
while (!LIST_EMPTY(&(pif->vlan_list)))
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Remove all VLANs from peer intf %s", pif->name);
|
||||
RB_FOREACH_SAFE(vlan, vlan_rb_tree, &(pif->vlan_tree), vlan_temp)
|
||||
{
|
||||
pvlan = LIST_FIRST(&(pif->vlan_list));
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d",
|
||||
pif->name, pvlan->vid);
|
||||
LIST_REMOVE(pvlan, port_next);
|
||||
free(pvlan);
|
||||
VLAN_RB_REMOVE(vlan_rb_tree, &(pif->vlan_tree), vlan);
|
||||
free(vlan);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -497,73 +567,86 @@ void peer_if_destroy(struct PeerInterface* pif)
|
||||
return;
|
||||
}
|
||||
|
||||
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_key = { 0 };
|
||||
char vlan_name[16] = "";
|
||||
|
||||
sprintf(vlan_name, "Vlan%d", vid);
|
||||
|
||||
/* traverse 1 time */
|
||||
LIST_FOREACH(vlan, &(local_if->vlan_list), port_next)
|
||||
{
|
||||
if (vlan->vid == vid)
|
||||
break;
|
||||
}
|
||||
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
|
||||
vlan_key.vid = vid;
|
||||
|
||||
vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), &vlan_key);
|
||||
|
||||
if (!vlan)
|
||||
{
|
||||
vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID));
|
||||
if (!vlan)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Add %s to VLAN %d", local_if->name, vid);
|
||||
vlan_info_init(vlan);
|
||||
vlan->vid = vid;
|
||||
vlan->vlan_itf = local_if_find_by_name(vlan_name);
|
||||
|
||||
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;
|
||||
LIST_INSERT_HEAD(&(local_if->vlan_list), vlan, port_next);
|
||||
RB_INSERT(vlan_rb_tree, &(local_if->vlan_tree), vlan);
|
||||
}
|
||||
|
||||
vlan_info_init(vlan);
|
||||
vlan->vid = vid;
|
||||
vlan->vlan_removed = 0;
|
||||
vlan->vlan_itf = local_if_find_by_name(vlan_name);
|
||||
|
||||
update_if_ipmac_on_standby(local_if);
|
||||
|
||||
// update_if_ipmac_on_standby(local_if, 5);
|
||||
if (vlan->vlan_itf)
|
||||
{
|
||||
if (local_if->is_peer_link)
|
||||
{
|
||||
update_vlan_if_mac_on_standby(vlan->vlan_itf, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "skip VLAN MAC update for vlan %d interface %s ", vid, local_if->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void local_if_del_vlan(struct LocalInterface* local_if, uint16_t vid)
|
||||
{
|
||||
struct VLAN_ID *vlan = NULL;
|
||||
struct VLAN_ID vlan_key = { 0 };
|
||||
|
||||
/* traverse 1 time */
|
||||
LIST_FOREACH(vlan, &(local_if->vlan_list), port_next)
|
||||
{
|
||||
if (vlan->vid == vid)
|
||||
break;
|
||||
}
|
||||
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
|
||||
vlan_key.vid = vid;
|
||||
|
||||
vlan = RB_FIND(vlan_rb_tree, &(local_if->vlan_tree), &vlan_key);
|
||||
|
||||
if (vlan != NULL)
|
||||
{
|
||||
LIST_REMOVE(vlan, port_next);
|
||||
VLAN_RB_REMOVE(vlan_rb_tree, &(local_if->vlan_tree), vlan);
|
||||
free(vlan);
|
||||
local_if->port_config_sync = 1;
|
||||
local_if->vlan_count -=1;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d, count %d", local_if->name, vid, local_if->vlan_count);
|
||||
}
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", local_if->name, vid);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void local_if_del_all_vlan(struct LocalInterface* lif)
|
||||
{
|
||||
struct VLAN_ID* vlan = NULL;
|
||||
struct VLAN_ID* vlan_temp = NULL;
|
||||
|
||||
while (!LIST_EMPTY(&(lif->vlan_list)))
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Remove all VLANs from %s", lif->name);
|
||||
RB_FOREACH_SAFE(vlan, vlan_rb_tree, &(lif->vlan_tree), vlan_temp)
|
||||
{
|
||||
vlan = LIST_FIRST(&(lif->vlan_list));
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove %s from VLAN %d", lif->name, vlan->vid);
|
||||
LIST_REMOVE(vlan, port_next);
|
||||
VLAN_RB_REMOVE(vlan_rb_tree, &(lif->vlan_tree), vlan);
|
||||
lif->vlan_count -=1;
|
||||
free(vlan);
|
||||
}
|
||||
|
||||
@ -574,34 +657,30 @@ void local_if_del_all_vlan(struct LocalInterface* lif)
|
||||
int peer_if_add_vlan(struct PeerInterface* peer_if, uint16_t vlan_id)
|
||||
{
|
||||
struct VLAN_ID *peer_vlan = NULL;
|
||||
struct VLAN_ID vlan_key = { 0 };
|
||||
char vlan_name[16] = "";
|
||||
|
||||
sprintf(vlan_name, "Vlan%d", vlan_id);
|
||||
|
||||
/* traverse 1 time */
|
||||
LIST_FOREACH(peer_vlan, &(peer_if->vlan_list), port_next)
|
||||
{
|
||||
if (peer_vlan->vid == vlan_id)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Update VLAN ID %d for peer intf %s", peer_vlan->vid, peer_if->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(&vlan_key, 0, sizeof(struct VLAN_ID));
|
||||
vlan_key.vid = vlan_id;
|
||||
|
||||
peer_vlan = RB_FIND(vlan_rb_tree, &(peer_if->vlan_tree), &vlan_key);
|
||||
|
||||
if (!peer_vlan)
|
||||
{
|
||||
peer_vlan = (struct VLAN_ID*)malloc(sizeof(struct VLAN_ID));
|
||||
if (!peer_vlan)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Add peer intf %s to VLAN %d", peer_if->name, vlan_id);
|
||||
LIST_INSERT_HEAD(&(peer_if->vlan_list), peer_vlan, port_next);
|
||||
vlan_info_init(peer_vlan);
|
||||
peer_vlan->vid = vlan_id;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
vlan_info_init(peer_vlan);
|
||||
peer_vlan->vid = vlan_id;
|
||||
peer_vlan->vlan_removed = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -610,14 +689,15 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if)
|
||||
{
|
||||
struct VLAN_ID *peer_vlan = NULL;
|
||||
struct VLAN_ID *peer_vlan_next = NULL;
|
||||
struct VLAN_ID *vlan_temp = NULL;
|
||||
|
||||
/* traverse 1 time */
|
||||
LIST_FOREACH(peer_vlan_next, &(peer_if->vlan_list), port_next)
|
||||
RB_FOREACH_SAFE(peer_vlan_next, vlan_rb_tree, &(peer_if->vlan_tree), vlan_temp)
|
||||
{
|
||||
if (peer_vlan != NULL)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid);
|
||||
LIST_REMOVE(peer_vlan, port_next);
|
||||
VLAN_RB_REMOVE(vlan_rb_tree, &(peer_if->vlan_tree), peer_vlan);
|
||||
free(peer_vlan);
|
||||
peer_vlan = NULL;
|
||||
|
||||
@ -629,7 +709,7 @@ int peer_if_clean_unused_vlan(struct PeerInterface* peer_if)
|
||||
if (peer_vlan != NULL)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Remove peer intf %s from VLAN %d", peer_if->name, peer_vlan->vid);
|
||||
LIST_REMOVE(peer_vlan, port_next);
|
||||
VLAN_RB_REMOVE(vlan_rb_tree, &(peer_if->vlan_tree), peer_vlan);
|
||||
free(peer_vlan);
|
||||
}
|
||||
|
||||
@ -660,9 +740,32 @@ int set_sys_arp_accept_flag(char* ifname, int flag)
|
||||
memset(cmd, 0, 64);
|
||||
snprintf(cmd, 63, "echo %d > /proc/sys/net/ipv4/conf/%s/arp_accept", flag, ifname);
|
||||
if (system(cmd))
|
||||
ICCPD_LOG_WARN(__func__, "Failed to execute cmd = %s", flag, cmd);
|
||||
ICCPD_LOG_WARN(__func__, "Failed to execute cmd = %s", cmd);
|
||||
}
|
||||
|
||||
fclose(file_ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
int local_if_l3_proto_enabled(const char* ifname)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
struct LocalInterface* local_if = NULL;
|
||||
|
||||
if (!ifname)
|
||||
return 0;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
return 0;
|
||||
|
||||
LIST_FOREACH(local_if, &(sys->lif_list), system_next)
|
||||
{
|
||||
if (strcmp(local_if->name, ifname) == 0)
|
||||
{
|
||||
if (local_if->is_l3_proto_enabled)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -48,6 +48,14 @@
|
||||
*
|
||||
******************************************************/
|
||||
|
||||
//this needs to be fine tuned
|
||||
#define PEER_SOCK_SND_BUF_LEN (6 * 1024 * 1024)
|
||||
#define PEER_SOCK_RCV_BUF_LEN (6 * 1024 * 1024)
|
||||
#define RECV_RETRY_INTERVAL_USEC 100000
|
||||
#define RECV_RETRY_MAX 10
|
||||
|
||||
extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size);
|
||||
|
||||
static int session_conn_thread_lock(pthread_mutex_t *conn_mutex)
|
||||
{
|
||||
return 1; /*pthread_mutex_lock(conn_mutex);*/
|
||||
@ -71,10 +79,10 @@ static void heartbeat_check(struct CSM *csm)
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (time(NULL) - csm->heartbeat_update_time) > HEARTBEAT_TIMEOUT_SEC)
|
||||
if ( (time(NULL) - csm->heartbeat_update_time) > csm->session_timeout)
|
||||
{
|
||||
/* hearbeat timeout*/
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "iccpd connection timeout (heartbeat)");
|
||||
ICCPD_LOG_WARN("ICCP_FSM", "iccpd connection timeout (heartbeat)");
|
||||
scheduler_session_disconnect_handler(csm);
|
||||
}
|
||||
|
||||
@ -106,15 +114,13 @@ static int scheduler_transit_fsm()
|
||||
iccp_csm_transit(csm);
|
||||
app_csm_transit(csm);
|
||||
mlacp_fsm_transit(csm);
|
||||
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE && (time(NULL) - sys->csm_trans_time) >= 60)
|
||||
{
|
||||
iccp_get_fdb_change_from_syncd();
|
||||
sys->csm_trans_time = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
local_if_change_flag_clear();
|
||||
//lif->changed flag is marked for state change for lif, for active node when
|
||||
//it is in STAGE2 where it receiving cfg sync from peer if there is any po
|
||||
//state change that change is not sent and this clear clears the marking and
|
||||
//thus remote state is not updated; so commenting this out
|
||||
//local_if_change_flag_clear();
|
||||
local_if_purge_clear();
|
||||
|
||||
return 1;
|
||||
@ -131,6 +137,9 @@ int scheduler_csm_read_callback(struct CSM* csm)
|
||||
size_t data_len = 0;
|
||||
size_t pos = 0;
|
||||
int recv_len = 0, len = 0, retval;
|
||||
int num_retry = 0;
|
||||
int total_retry_time = 0;
|
||||
int total_data_len = 0;
|
||||
|
||||
if (csm->sock_fd <= 0)
|
||||
return MCLAG_ERROR;
|
||||
@ -138,6 +147,7 @@ int scheduler_csm_read_callback(struct CSM* csm)
|
||||
memset(peer_msg, 0, CSM_BUFFER_SIZE);
|
||||
|
||||
recv_len = 0;
|
||||
errno = 0;
|
||||
|
||||
while (recv_len != sizeof(LDPHdr))
|
||||
{
|
||||
@ -145,38 +155,92 @@ int scheduler_csm_read_callback(struct CSM* csm)
|
||||
if (len == -1)
|
||||
{
|
||||
perror("recv(). Error");
|
||||
ICCPD_LOG_WARN("ICCP_FSM", "Peer disconnect for header read error[%s] len = -1 till now received len = %d ", strerror(errno), recv_len);
|
||||
SYSTEM_INCR_HDR_READ_SOCK_ERR_COUNTER(system_get_instance());
|
||||
goto recv_err;
|
||||
}
|
||||
else if (len == 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for receive error");
|
||||
ICCPD_LOG_WARN("ICCP_FSM", "Peer disconnect for header read error[%s] len = 0, till now received len = %d ",strerror(errno), recv_len);
|
||||
SYSTEM_INCR_HDR_READ_SOCK_ZERO_LEN_COUNTER(system_get_instance());
|
||||
goto recv_err;
|
||||
}
|
||||
recv_len += len;
|
||||
/*usleep(100);*/
|
||||
}
|
||||
|
||||
data_len = ntohs(ldp_hdr->msg_len) - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS;
|
||||
if (ntohs(ldp_hdr->msg_len) >= MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS)
|
||||
{
|
||||
data_len = ntohs(ldp_hdr->msg_len) - MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_ERR("ICCP_FSM", "Peer disconnect for invalid data error; length[%d] msg_type[0x%x] ", ntohs(ldp_hdr->msg_len), ntohs(ldp_hdr->msg_type));
|
||||
SYSTEM_INCR_INVALID_PEER_MSG_COUNTER(system_get_instance());
|
||||
goto recv_err;
|
||||
}
|
||||
total_data_len = data_len;
|
||||
pos = 0;
|
||||
|
||||
while (data_len > 0)
|
||||
{
|
||||
recv_len = recv(csm->sock_fd, &data[pos], data_len, 0);
|
||||
/* When consecutive CCP session flaps happen, recv() call got stuck.
|
||||
* Change recv() to non-blocking with retry mechanism. If max
|
||||
* retry reaches, attempt one more retry after waiting for one KA
|
||||
* interval before bringing down the session.
|
||||
*/
|
||||
recv_len = recv(csm->sock_fd, &data[pos], data_len, MSG_DONTWAIT);
|
||||
if (recv_len == -1)
|
||||
{
|
||||
perror("continue recv(). Error");
|
||||
goto recv_err;
|
||||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
|
||||
{
|
||||
ICCPD_LOG_NOTICE(
|
||||
"ICCP_FSM", "Non-blocking recv total/pending len %d/%d, errno %d, num_retry %d",
|
||||
total_data_len, data_len, errno, num_retry);
|
||||
++num_retry;
|
||||
if (num_retry > RECV_RETRY_MAX)
|
||||
{
|
||||
ICCPD_LOG_ERR(
|
||||
"ICCP_FSM", "Non-blocking recv() retry failed, total/pending len %d/%d",
|
||||
total_data_len, data_len);
|
||||
SYSTEM_INCR_RX_RETRY_FAIL_COUNTER(system_get_instance());
|
||||
goto recv_err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (num_retry == RECV_RETRY_MAX)
|
||||
usleep((csm->session_timeout * 1000000) - total_retry_time);
|
||||
else
|
||||
{
|
||||
total_retry_time += (num_retry * RECV_RETRY_INTERVAL_USEC);
|
||||
usleep(num_retry * RECV_RETRY_INTERVAL_USEC);
|
||||
}
|
||||
recv_len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
perror("continue recv() Error");
|
||||
ICCPD_LOG_WARN("ICCP_FSM", "Peer data read error; recv_len:%d data_len:%d, errno %d",
|
||||
recv_len, data_len, errno);
|
||||
SYSTEM_INCR_TLV_READ_SOCK_ERR_COUNTER(system_get_instance());
|
||||
goto recv_err;
|
||||
}
|
||||
}
|
||||
else if (recv_len == 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Peer disconnect for read error");
|
||||
ICCPD_LOG_WARN("ICCP_FSM", "Peer disconnect for data read error; recv_len:%d data_len:%d ", recv_len, data_len);
|
||||
SYSTEM_INCR_TLV_READ_SOCK_ZERO_LEN_COUNTER(system_get_instance());
|
||||
goto recv_err;
|
||||
}
|
||||
data_len -= recv_len;
|
||||
pos += recv_len;
|
||||
/*usleep(100);*/
|
||||
}
|
||||
|
||||
if (num_retry > 0)
|
||||
{
|
||||
SYSTEM_SET_RETRY_COUNTER(system_get_instance(), num_retry);
|
||||
}
|
||||
retval = iccp_csm_init_msg(&msg, peer_msg, ntohs(ldp_hdr->msg_len) + MSG_L_INCLUD_U_BIT_MSG_T_L_FIELDS);
|
||||
if (retval == 0)
|
||||
{
|
||||
@ -224,21 +288,21 @@ int scheduler_server_accept()
|
||||
if (!csm)
|
||||
{
|
||||
/* can't find csm with peer ip*/
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
|
||||
ICCPD_LOG_NOTICE("ICCP_FSM", "csm null with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
|
||||
goto reject_client;
|
||||
}
|
||||
|
||||
if (csm->sock_fd > 0)
|
||||
{
|
||||
/* peer already connected*/
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
|
||||
ICCPD_LOG_NOTICE("ICCP_FSM", "csm sock is connected with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
|
||||
goto reject_client;
|
||||
}
|
||||
|
||||
if ((ret = scheduler_check_csm_config(csm)) < 0)
|
||||
{
|
||||
/* csm config error*/
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
|
||||
ICCPD_LOG_NOTICE("ICCP_FSM", "csm config error with peer ip [%s]", inet_ntoa(client_addr.sin_addr));
|
||||
goto reject_client;
|
||||
}
|
||||
}
|
||||
@ -257,6 +321,8 @@ int scheduler_server_accept()
|
||||
|
||||
struct epoll_event event;
|
||||
int err;
|
||||
int send_buf_len = PEER_SOCK_SND_BUF_LEN;
|
||||
int recv_buf_len = PEER_SOCK_RCV_BUF_LEN;
|
||||
event.data.fd = new_fd;
|
||||
event.events = EPOLLIN;
|
||||
err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, new_fd, &event);
|
||||
@ -267,6 +333,14 @@ int scheduler_server_accept()
|
||||
}
|
||||
|
||||
csm->sock_fd = new_fd;
|
||||
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_SNDBUF, &send_buf_len, sizeof(send_buf_len)) == -1)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set socket send buf option failed. Error");
|
||||
}
|
||||
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)) == -1)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set socket recv buf option failed. Error");
|
||||
}
|
||||
csm->current_state = ICCP_NONEXISTENT;
|
||||
FD_SET(new_fd, &(sys->readfd));
|
||||
sys->readfd_count++;
|
||||
@ -293,6 +367,8 @@ void iccp_get_start_type(struct System* sys)
|
||||
if (strstr(g_csm_buf, "SONIC_BOOT_TYPE=warm"))
|
||||
sys->warmboot_start = WARM_REBOOT;
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "Start ICCP: warm reboot %s",
|
||||
(sys->warmboot_start == WARM_REBOOT)? "yes" : "no");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -309,8 +385,10 @@ void scheduler_init()
|
||||
iccp_sys_local_if_list_get_init();
|
||||
iccp_sys_local_if_list_get_addr();
|
||||
/*Interfaces must be created before this func called*/
|
||||
//no need to create iccpd config from startup file, it will be done through
|
||||
//cli
|
||||
iccp_config_from_file(sys->config_file_path);
|
||||
|
||||
|
||||
/*Get kernel ARP info */
|
||||
iccp_neigh_get_init();
|
||||
|
||||
@ -331,7 +409,6 @@ void scheduler_init()
|
||||
return;
|
||||
}
|
||||
|
||||
extern int mlacp_prepare_for_warm_reboot(struct CSM* csm, char* buf, size_t max_buf_size);
|
||||
void mlacp_sync_send_warmboot_flag()
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
@ -350,7 +427,7 @@ void mlacp_sync_send_warmboot_flag()
|
||||
iccp_csm_send(csm, g_csm_buf, msg_len);
|
||||
}
|
||||
}
|
||||
|
||||
ICCPD_LOG_DEBUG("ICCP_FSM", "Send warmboot flag to peer. Start warmboot");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -542,12 +619,23 @@ void session_client_conn_handler(struct CSM *csm)
|
||||
/* Conn OK*/
|
||||
struct epoll_event event;
|
||||
int err;
|
||||
int send_buf_len = PEER_SOCK_SND_BUF_LEN;
|
||||
int recv_buf_len = PEER_SOCK_RCV_BUF_LEN;
|
||||
event.data.fd = connFd;
|
||||
event.events = EPOLLIN;
|
||||
err = epoll_ctl(sys->epoll_fd, EPOLL_CTL_ADD, connFd, &event);
|
||||
if (err)
|
||||
goto conn_fail;
|
||||
csm->sock_fd = connFd;
|
||||
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_SNDBUF, &send_buf_len, sizeof(send_buf_len)) == -1)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set socket send buf option failed. Error");
|
||||
}
|
||||
if (setsockopt(csm->sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf_len, sizeof(recv_buf_len)) == -1)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set socket recv buf option failed. Error");
|
||||
}
|
||||
|
||||
FD_SET(connFd, &(sys->readfd));
|
||||
sys->readfd_count++;
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "Connect to server %s sucess .", csm->peer_ip);
|
||||
@ -707,6 +795,7 @@ int scheduler_check_csm_config(struct CSM* csm)
|
||||
{
|
||||
lif->is_peer_link = 1;
|
||||
csm->peer_link_if = lif;
|
||||
set_peerlink_learn_kernel(csm, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -742,32 +831,66 @@ int scheduler_unregister_sock_read_event_callback(struct CSM* csm)
|
||||
void scheduler_session_disconnect_handler(struct CSM* csm)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
struct If_info * cif = NULL;
|
||||
|
||||
if ((sys = system_get_instance()) == NULL )
|
||||
return;
|
||||
|
||||
struct epoll_event event;
|
||||
|
||||
if (csm == NULL)
|
||||
return;
|
||||
|
||||
ICCPD_LOG_NOTICE("ICCP_FSM", "scheduler session disconnect handler");
|
||||
|
||||
session_conn_thread_lock(&csm->conn_mutex);
|
||||
scheduler_unregister_sock_read_event_callback(csm);
|
||||
if (csm->sock_fd > 0)
|
||||
{
|
||||
event.data.fd = csm->sock_fd;
|
||||
event.events = EPOLLIN;
|
||||
epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event);
|
||||
|
||||
close(csm->sock_fd);
|
||||
csm->sock_fd = -1;
|
||||
scheduler_csm_socket_cleanup(csm, 1);
|
||||
}
|
||||
|
||||
mlacp_peer_disconn_handler(csm);
|
||||
MLACP(csm).current_state = MLACP_STATE_INIT;
|
||||
iccp_csm_status_reset(csm, 0);
|
||||
|
||||
time(&csm->connTimePrev);
|
||||
session_conn_thread_unlock(&csm->conn_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void scheduler_csm_socket_cleanup(struct CSM* csm, int location)
|
||||
{
|
||||
struct System* sys;
|
||||
struct epoll_event event;
|
||||
|
||||
sys = system_get_instance();
|
||||
if (sys == NULL)
|
||||
return;
|
||||
|
||||
if (csm == NULL)
|
||||
return;
|
||||
|
||||
if (csm->sock_fd <= 0)
|
||||
return
|
||||
|
||||
event.data.fd = csm->sock_fd;
|
||||
event.events = EPOLLIN;
|
||||
if (epoll_ctl(sys->epoll_fd, EPOLL_CTL_DEL, csm->sock_fd, &event) != 0)
|
||||
{
|
||||
ICCPD_LOG_ERR("ICCP_FSM", "CSM socket %d epoll del error %d, location %d",
|
||||
csm->sock_fd, errno, location);
|
||||
}
|
||||
if (close(csm->sock_fd) != 0)
|
||||
{
|
||||
ICCPD_LOG_ERR("ICCP_FSM", "CSM socket %d close error %d, location %d",
|
||||
csm->sock_fd, errno, location);
|
||||
SYSTEM_INCR_SOCKET_CLOSE_ERR_COUNTER(system_get_instance());
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_NOTICE("ICCP_FSM", "CSM socket %d close, location %d",
|
||||
csm->sock_fd, location);
|
||||
}
|
||||
csm->sock_fd = -1;
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,17 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netlink/msg.h>
|
||||
|
||||
#include "../include/iccp_csm.h"
|
||||
#include "../include/logger.h"
|
||||
#include "../include/iccp_netlink.h"
|
||||
#include "../include/scheduler.h"
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
#include "../include/iccp_ifm.h"
|
||||
|
||||
#define ETHER_ADDR_LEN 6
|
||||
char mac_print_str[ETHER_ADDR_STR_LEN];
|
||||
|
||||
/* Singleton */
|
||||
struct System* system_get_instance()
|
||||
@ -53,6 +59,7 @@ void system_init(struct System* sys)
|
||||
if (sys == NULL )
|
||||
return;
|
||||
|
||||
memset(sys, 0, sizeof(struct System));
|
||||
sys->server_fd = -1;
|
||||
sys->sync_fd = -1;
|
||||
sys->sync_ctrl_fd = -1;
|
||||
@ -65,6 +72,8 @@ void system_init(struct System* sys)
|
||||
LIST_INIT(&(sys->csm_list));
|
||||
LIST_INIT(&(sys->lif_list));
|
||||
LIST_INIT(&(sys->lif_purge_list));
|
||||
LIST_INIT(&(sys->unq_ip_if_list));
|
||||
LIST_INIT(&(sys->pending_vlan_mbr_if_list));
|
||||
|
||||
sys->log_file_path = strdup("/var/log/iccpd.log");
|
||||
sys->cmd_file_path = strdup("/var/run/iccpd/iccpd.vty");
|
||||
@ -88,15 +97,21 @@ void system_finalize()
|
||||
struct System* sys = NULL;
|
||||
struct CSM* csm = NULL;
|
||||
struct LocalInterface* local_if = NULL;
|
||||
struct Unq_ip_If_info* unq_ip_if = NULL;
|
||||
|
||||
if ((sys = system_get_instance()) == NULL )
|
||||
return;
|
||||
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "System resource pool is destructing.");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__,
|
||||
"System resource pool is destructing. Warmboot exit (%d)",
|
||||
sys->warmboot_exit);
|
||||
|
||||
while (!LIST_EMPTY(&(sys->csm_list)))
|
||||
{
|
||||
csm = LIST_FIRST(&(sys->csm_list));
|
||||
/* Remove ICCP info from STATE_DB if it is not warm reboot */
|
||||
if (sys->warmboot_exit != WARM_REBOOT)
|
||||
mlacp_link_del_iccp_info(csm->mlag_id);
|
||||
iccp_csm_finalize(csm);
|
||||
}
|
||||
|
||||
@ -115,6 +130,16 @@ void system_finalize()
|
||||
local_if_finalize(local_if);
|
||||
}
|
||||
|
||||
//remove all pending vlan membership entries
|
||||
del_all_pending_vlan_mbr_ifs(sys);
|
||||
|
||||
while (!LIST_EMPTY(&(sys->unq_ip_if_list)))
|
||||
{
|
||||
unq_ip_if = LIST_FIRST(&(sys->unq_ip_if_list));
|
||||
LIST_REMOVE(unq_ip_if, if_next);
|
||||
free(unq_ip_if);
|
||||
}
|
||||
|
||||
iccp_system_dinit_netlink_socket();
|
||||
|
||||
if (sys->log_file_path != NULL )
|
||||
@ -185,6 +210,34 @@ struct CSM* system_get_csm_by_peer_ip(const char* peer_ip)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//function to get CSM by peer interface name
|
||||
struct CSM* system_get_csm_by_peer_ifname(char *ifname)
|
||||
{
|
||||
struct CSM *csm = NULL;
|
||||
struct System* sys = NULL;
|
||||
|
||||
if (!ifname)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((sys = system_get_instance()) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* traverse all CSM and find matching csm with peer ifname */
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
//return matching csm
|
||||
if (strcmp(ifname, csm->peer_itf_name) == 0)
|
||||
{
|
||||
return csm;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct CSM* system_get_csm_by_mlacp_id(int id)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
@ -201,3 +254,146 @@ struct CSM* system_get_csm_by_mlacp_id(int id)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct CSM* system_get_first_csm()
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
struct CSM* csm = NULL;
|
||||
|
||||
if ((sys = system_get_instance()) == NULL )
|
||||
return NULL;
|
||||
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
return csm;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SYNCD_TX_DBG_CNTR_MSG_e system_syncdtx_to_dbg_msg_type(uint32_t msg_type)
|
||||
{
|
||||
switch(msg_type)
|
||||
{
|
||||
case MCLAG_MSG_TYPE_PORT_ISOLATE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_PORT_ISOLATE;
|
||||
|
||||
case MCLAG_MSG_TYPE_PORT_MAC_LEARN_MODE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_PORT_MAC_LEARN_MODE;
|
||||
|
||||
case MCLAG_MSG_TYPE_FLUSH_FDB:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_FLUSH_FDB;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_MAC:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_IF_MAC;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_FDB:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_FDB;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_ENABLE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_ENABLE;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_TRAFFIC_DIST_DISABLE;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_ICCP_STATE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_STATE;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_ICCP_ROLE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_ROLE;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_ICCP_SYSTEM_ID:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_SYSTEM_ID;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_REMOTE_IF_STATE;
|
||||
|
||||
case MCLAG_MSG_TYPE_DEL_ICCP_INFO:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_DEL_ICCP_INFO;
|
||||
|
||||
case MCLAG_MSG_TYPE_DEL_REMOTE_IF_INFO:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_DEL_REMOTE_IF_INFO;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_PEER_LINK_ISOLATION:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_PEER_LINK_ISOLATION;
|
||||
|
||||
case MCLAG_MSG_TYPE_SET_ICCP_PEER_SYSTEM_ID:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_SET_ICCP_PEER_SYSTEM_ID;
|
||||
|
||||
default:
|
||||
return SYNCD_TX_DBG_CNTR_MSG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
SYNCD_RX_DBG_CNTR_MSG_e system_syncdrx_to_dbg_msg_type(uint32_t msg_type)
|
||||
{
|
||||
switch(msg_type)
|
||||
{
|
||||
case MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION:
|
||||
return SYNCD_RX_DBG_CNTR_MSG_MAC;
|
||||
case MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN:
|
||||
return SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_DOMAIN;
|
||||
case MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE:
|
||||
return SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_IFACE;
|
||||
case MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP:
|
||||
return SYNCD_RX_DBG_CNTR_MSG_CFG_MCLAG_UNIQUE_IP;
|
||||
case MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES:
|
||||
return SYNCD_RX_DBG_CNTR_MSG_VLAN_MBR_UPDATES;
|
||||
default:
|
||||
return SYNCD_RX_DBG_CNTR_MSG_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
char *mac_addr_to_str(uint8_t mac_addr[ETHER_ADDR_LEN])
|
||||
{
|
||||
memset(mac_print_str, 0, sizeof(mac_print_str));
|
||||
snprintf(mac_print_str, sizeof(mac_print_str), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
|
||||
return mac_print_str;
|
||||
}
|
||||
|
||||
void system_update_netlink_counters(
|
||||
uint16_t netlink_msg_type,
|
||||
struct nlmsghdr *nlh)
|
||||
{
|
||||
struct System *sys;
|
||||
struct ndmsg *ndm = NLMSG_DATA(nlh);
|
||||
|
||||
sys = system_get_instance();
|
||||
if (!sys)
|
||||
return;
|
||||
|
||||
switch (netlink_msg_type)
|
||||
{
|
||||
case RTM_NEWLINK:
|
||||
++sys->dbg_counters.newlink_count;
|
||||
break;
|
||||
case RTM_DELLINK:
|
||||
++sys->dbg_counters.dellink_count;
|
||||
break;
|
||||
case RTM_NEWNEIGH:
|
||||
++sys->dbg_counters.newnbr_count;
|
||||
if (ndm->ndm_family == AF_BRIDGE)
|
||||
++sys->dbg_counters.newmac_count;
|
||||
break;
|
||||
case RTM_DELNEIGH:
|
||||
++sys->dbg_counters.delnbr_count;
|
||||
if (ndm->ndm_family == AF_BRIDGE)
|
||||
++sys->dbg_counters.delmac_count;
|
||||
break;
|
||||
case RTM_NEWADDR:
|
||||
++sys->dbg_counters.newaddr_count;
|
||||
break;
|
||||
case RTM_DELADDR:
|
||||
++sys->dbg_counters.deladdr_count;
|
||||
break;
|
||||
default:
|
||||
++sys->dbg_counters.unknown_type_count;
|
||||
if (sys->dbg_counters.unknown_type_count < 5)
|
||||
{
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "NETLINK_COUNTER: Unknown type %d", netlink_msg_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user