[iccpd]: ICCPD support IPv6 ND (#4422)
accomplish it according MCLAG HLD document, the principle is similar to IPv4 ARP.
This commit is contained in:
parent
087e5fbf78
commit
4c55adfd6e
@ -29,6 +29,7 @@
|
||||
|
||||
extern int iccp_mclag_config_dump(char * *buf, int *num, int mclag_id);
|
||||
extern int iccp_arp_dump(char * *buf, int *num, int mclag_id);
|
||||
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);
|
||||
|
@ -45,7 +45,9 @@
|
||||
#ifndef INET_ADDRSTRLEN
|
||||
#define INET_ADDRSTRLEN 16
|
||||
#endif /* INET_ADDRSTRLEN */
|
||||
|
||||
#ifndef INET6_ADDRSTRLEN
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
#endif /* INET6_ADDRSTRLEN */
|
||||
/* For socket binding */
|
||||
#define ICCP_TCP_PORT 8888
|
||||
#define MAX_ACCEPT_CONNETIONS 20
|
||||
|
@ -28,9 +28,10 @@
|
||||
|
||||
int iccp_sys_local_if_list_get_init();
|
||||
|
||||
int iccp_arp_get_init();
|
||||
int iccp_neigh_get_init();
|
||||
|
||||
void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, uint8_t mac_addr[ETHER_ADDR_LEN]);
|
||||
void do_ndisc_update_from_reply_packet(unsigned int ifindex, char *ipv6_addr, uint8_t mac_addr[ETHER_ADDR_LEN]);
|
||||
|
||||
int do_one_neigh_request(struct nlmsghdr *n);
|
||||
|
||||
|
@ -31,6 +31,25 @@
|
||||
|
||||
#include "../include/system.h"
|
||||
#include "../include/port.h"
|
||||
#include <netinet/icmp6.h>
|
||||
#include <linux/ipv6.h>
|
||||
|
||||
#define NDISC_NEIGHBOUR_ADVERTISEMENT 136
|
||||
#define ND_OPT_TARGET_LL_ADDR 2
|
||||
#define NEXTHDR_ICMP 58
|
||||
|
||||
struct nd_msg
|
||||
{
|
||||
struct icmp6_hdr icmph;
|
||||
struct in6_addr target;
|
||||
__u8 opt[0];
|
||||
};
|
||||
|
||||
struct in6_pktinfo
|
||||
{
|
||||
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
|
||||
unsigned int ipi6_ifindex; /* send/recv interface index */
|
||||
};
|
||||
|
||||
int iccp_get_port_member_list(struct LocalInterface* lif);
|
||||
void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg);
|
||||
@ -41,6 +60,7 @@ 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_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_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif);
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,7 @@ enum MLACP_SYNC_STATE
|
||||
MLACP_SYNC_AGGINFO,
|
||||
MLACP_SYNC_PEERLINKINFO,
|
||||
MLACP_SYNC_ARP_INFO,
|
||||
MLACP_SYNC_NDISC_INFO,
|
||||
MLACP_SYNC_DONE,
|
||||
};
|
||||
|
||||
@ -85,6 +86,8 @@ struct mLACP
|
||||
TAILQ_HEAD(mlacp_msg_list, Msg) mlacp_msg_list;
|
||||
TAILQ_HEAD(arp_msg_list, Msg) arp_msg_list;
|
||||
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;
|
||||
|
||||
|
@ -43,17 +43,17 @@ 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);
|
||||
|
||||
int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac);
|
||||
int mlacp_fsm_arp_del(char *ifname, uint32_t ip);
|
||||
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);
|
||||
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);
|
||||
|
||||
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();
|
||||
|
@ -46,6 +46,7 @@ int mlacp_prepare_for_sync_data_tlv(struct CSM* csm, char* buf, size_t max_buf_s
|
||||
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_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);
|
||||
|
@ -36,12 +36,13 @@ 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_heartbeat(struct CSM* csm, struct mLACPHeartbeatTLV* tlv);
|
||||
|
||||
int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv);
|
||||
void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg);
|
||||
|
||||
void mlacp_enqueue_ndisc(struct CSM *csm, struct Msg* msg);
|
||||
int mlacp_fsm_update_Agg_conf(struct CSM* csm, mLACPAggConfigTLV* portconf);
|
||||
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);
|
||||
|
@ -374,6 +374,14 @@ struct ARPMsg
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
struct NDISCMsg
|
||||
{
|
||||
uint8_t op_type;
|
||||
char ifname[MAX_L_PORT_NAME];
|
||||
uint32_t ipv6_addr[4];
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
/*
|
||||
* ARP Information TLV
|
||||
*/
|
||||
@ -385,6 +393,17 @@ struct mLACPARPInfoTLV
|
||||
struct ARPMsg ArpEntry[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* NDISC Information TLV
|
||||
*/
|
||||
struct mLACPNDISCInfoTLV
|
||||
{
|
||||
ICCParameter icc_parameter;
|
||||
/* Local Interface ID */
|
||||
uint16_t num_of_entry;
|
||||
struct NDISCMsg NdiscEntry[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* NOS: STP Information TLV
|
||||
*/
|
||||
@ -413,11 +432,11 @@ struct mLACPWarmbootTLV
|
||||
uint8_t warmboot;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum ARP_OP_TYPE
|
||||
enum NEIGH_OP_TYPE
|
||||
{
|
||||
ARP_SYNC_LIF,
|
||||
ARP_SYNC_ADD,
|
||||
ARP_SYNC_DEL,
|
||||
NEIGH_SYNC_LIF,
|
||||
NEIGH_SYNC_ADD,
|
||||
NEIGH_SYNC_DEL,
|
||||
};
|
||||
|
||||
enum MAC_AGE_TYPE
|
||||
|
@ -98,7 +98,8 @@
|
||||
#define TLV_T_MLACP_STP_INFO 0x1037//no support
|
||||
#define TLV_T_MLACP_MAC_INFO 0x1038
|
||||
#define TLV_T_MLACP_WARMBOOT_FLAG 0x1039
|
||||
#define TLV_T_MLACP_LIST_END 0x104a //list end
|
||||
#define TLV_T_MLACP_NDISC_INFO 0x103A
|
||||
#define TLV_T_MLACP_LIST_END 0x104a // list end
|
||||
|
||||
/* Debug */
|
||||
static char* get_tlv_type_string(int type)
|
||||
|
@ -102,6 +102,8 @@ struct LocalInterface
|
||||
uint8_t state;
|
||||
uint32_t ipv4_addr;
|
||||
uint8_t prefixlen;
|
||||
uint32_t ipv6_addr[4];
|
||||
uint8_t prefixlen_v6;
|
||||
|
||||
uint8_t l3_mode;
|
||||
uint8_t l3_mac_addr[ETHER_ADDR_LEN];
|
||||
@ -139,6 +141,7 @@ 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);
|
||||
|
||||
|
@ -58,6 +58,7 @@ struct System
|
||||
int sync_fd;
|
||||
int sync_ctrl_fd;
|
||||
int arp_receive_fd;
|
||||
int ndisc_receive_fd;
|
||||
int epoll_fd;
|
||||
|
||||
struct nl_sock * genric_sock;
|
||||
|
@ -177,7 +177,7 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id)
|
||||
|
||||
mclagd_arp.op_type = iccpd_arp->op_type;
|
||||
memcpy(mclagd_arp.ifname, iccpd_arp->ifname, strlen(iccpd_arp->ifname));
|
||||
memcpy(mclagd_arp.ipv4_addr, show_ip_str(htonl(iccpd_arp->ipv4_addr)), 16);
|
||||
memcpy(mclagd_arp.ipv4_addr, show_ip_str(iccpd_arp->ipv4_addr), 16);
|
||||
memcpy(mclagd_arp.mac_addr, iccpd_arp->mac_addr, 6);
|
||||
|
||||
memcpy(arp_buf + MCLAGD_REPLY_INFO_HDR + arp_num * sizeof(struct mclagd_arp_msg),
|
||||
@ -204,6 +204,72 @@ int iccp_arp_dump(char * *buf, int *num, int mclag_id)
|
||||
return EXEC_TYPE_SUCCESS;
|
||||
}
|
||||
|
||||
int iccp_ndisc_dump(char * *buf, int *num, int mclag_id)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct CSM *csm = NULL;
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *iccpd_ndisc = NULL;
|
||||
struct mclagd_ndisc_msg mclagd_ndisc;
|
||||
int ndisc_num = 0;
|
||||
int id_exist = 0;
|
||||
char *ndisc_buf = NULL;
|
||||
int ndisc_buf_size = MCLAGDCTL_CMD_SIZE;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
{
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "cannot find sys!\n");
|
||||
return EXEC_TYPE_NO_EXIST_SYS;
|
||||
}
|
||||
|
||||
ndisc_buf = (char *)malloc(ndisc_buf_size);
|
||||
if (!ndisc_buf)
|
||||
return EXEC_TYPE_FAILED;
|
||||
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
if (mclag_id > 0)
|
||||
{
|
||||
if (csm->mlag_id == mclag_id)
|
||||
id_exist = 1;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
memset(&mclagd_ndisc, 0, sizeof(struct mclagd_ndisc_msg));
|
||||
iccpd_ndisc = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
mclagd_ndisc.op_type = iccpd_ndisc->op_type;
|
||||
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));
|
||||
|
||||
ndisc_num++;
|
||||
|
||||
if ((ndisc_num + 1) * sizeof(struct mclagd_ndisc_msg) > (ndisc_buf_size - MCLAGD_REPLY_INFO_HDR))
|
||||
{
|
||||
ndisc_buf_size += MCLAGDCTL_CMD_SIZE;
|
||||
ndisc_buf = (char *)realloc(ndisc_buf, ndisc_buf_size);
|
||||
if (!ndisc_buf)
|
||||
return EXEC_TYPE_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*buf = ndisc_buf;
|
||||
*num = ndisc_num;
|
||||
|
||||
if (mclag_id > 0 && !id_exist)
|
||||
return EXEC_TYPE_NO_EXIST_MCLAGID;
|
||||
|
||||
return EXEC_TYPE_SUCCESS;
|
||||
}
|
||||
|
||||
int iccp_mac_dump(char * *buf, int *num, int mclag_id)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
|
@ -137,34 +137,21 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int
|
||||
memset(buf, 0, MAX_BUFSIZE);
|
||||
msg_len = sizeof(struct ARPMsg);
|
||||
arp_msg = (struct ARPMsg*)&buf;
|
||||
arp_msg->op_type = ARP_SYNC_LIF;
|
||||
arp_msg->op_type = NEIGH_SYNC_LIF;
|
||||
sprintf(arp_msg->ifname, "%s", arp_lif->name);
|
||||
if (tb[NDA_DST])
|
||||
memcpy(&arp_msg->ipv4_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
|
||||
if (tb[NDA_LLADDR])
|
||||
memcpy(arp_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR]));
|
||||
|
||||
arp_msg->ipv4_addr = ntohl(arp_msg->ipv4_addr);
|
||||
arp_msg->ipv4_addr = arp_msg->ipv4_addr;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ARP type %s, state (%04X)(%d) ifindex [%d] (%s) ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "ARP type %s, state (%04X)(%d) ifindex [%d] (%s) ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]",
|
||||
msgtype == RTM_NEWNEIGH ? "New":"Del", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state),
|
||||
ndm->ndm_ifindex, arp_lif->name,
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)),
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
|
||||
/*Debug*/
|
||||
#if 0
|
||||
/* dump receive kernel ARP req*/
|
||||
fprintf(stderr, "\n======== Kernel ARP ==========\n");
|
||||
fprintf(stderr, " Type = [%d] (New=%d, Del=%d)\n", msgtype, RTM_NEWNEIGH, RTM_DELNEIGH);
|
||||
fprintf(stderr, " State = (%04X)(%d)\n", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state));
|
||||
fprintf(stderr, " ifindex = [%d] (%s)\n", ndm->ndm_ifindex, arp_msg->ifname);
|
||||
fprintf(stderr, " IP = [%s]\n", show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n",
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3],
|
||||
arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
fprintf(stderr, "==============================\n");
|
||||
#endif
|
||||
show_ip_str(arp_msg->ipv4_addr),
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4],
|
||||
arp_msg->mac_addr[5]);
|
||||
|
||||
/* Find MLACP itf, member of port-channel*/
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
@ -228,7 +215,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
msg = NULL;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Delete ARP %s", show_ip_str(arp_msg->ipv4_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -242,7 +229,7 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int
|
||||
arp_info->op_type = arp_msg->op_type;
|
||||
sprintf(arp_info->ifname, "%s", arp_msg->ifname);
|
||||
memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s", show_ip_str(arp_msg->ipv4_addr));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -256,31 +243,31 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int
|
||||
/* enquene lif_msg (add)*/
|
||||
if (!msg)
|
||||
{
|
||||
arp_msg->op_type = ARP_SYNC_LIF;
|
||||
arp_msg->op_type = NEIGH_SYNC_LIF;
|
||||
if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0)
|
||||
{
|
||||
mlacp_enqueue_arp(csm, msg);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s",
|
||||
arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s",
|
||||
arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr));
|
||||
}
|
||||
|
||||
/* enqueue iccp_msg (add)*/
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
arp_msg->op_type = ARP_SYNC_ADD;
|
||||
arp_msg->op_type = NEIGH_SYNC_ADD;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] message for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
show_ip_str(arp_msg->ipv4_addr));
|
||||
|
||||
}
|
||||
}
|
||||
@ -289,58 +276,218 @@ static void do_arp_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int
|
||||
/* enqueue iccp_msg (delete)*/
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
arp_msg->op_type = ARP_SYNC_DEL;
|
||||
arp_msg->op_type = NEIGH_SYNC_DEL;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[DEL] message for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[DEL] message for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
show_ip_str(arp_msg->ipv4_addr));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*Debug: dump for dequeue ARP Info*/
|
||||
#if 0
|
||||
fprintf(stderr, "\n======== ARP Info List ========\n");
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
fprintf(stderr, "type %d,ifname %s , ip %s\n", arp_msg->op_type, arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
}
|
||||
fprintf(stderr, "==============================\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*TEST dump for dequeue ARP message*/
|
||||
#if 0
|
||||
static void do_ndisc_learn_from_kernel(struct ndmsg *ndm, struct rtattr *tb[], int msgtype)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct CSM *csm = NULL;
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *ndisc_msg = NULL, *ndisc_info = NULL;
|
||||
struct VLAN_ID *vlan_id_list = NULL;
|
||||
struct Msg *msg_send = NULL;
|
||||
|
||||
while (MLACP(csm).arp_updated && !TAILQ_EMPTY(&(MLACP(csm).arp_msg_list)))
|
||||
char buf[MAX_BUFSIZE];
|
||||
size_t msg_len = 0;
|
||||
|
||||
struct LocalInterface *lif_po = NULL, *ndisc_lif = NULL;
|
||||
|
||||
int verify_neigh = 0;
|
||||
int neigh_update = 0;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
return;
|
||||
|
||||
/* Find local itf */
|
||||
if (!(ndisc_lif = local_if_find_by_ifindex(ndm->ndm_ifindex)))
|
||||
return;
|
||||
|
||||
/* create NDISC msg */
|
||||
memset(buf, 0, MAX_BUFSIZE);
|
||||
msg_len = sizeof(struct NDISCMsg);
|
||||
ndisc_msg = (struct NDISCMsg *)&buf;
|
||||
ndisc_msg->op_type = NEIGH_SYNC_LIF;
|
||||
sprintf(ndisc_msg->ifname, "%s", ndisc_lif->name);
|
||||
if (tb[NDA_DST])
|
||||
memcpy(&ndisc_msg->ipv6_addr, RTA_DATA(tb[NDA_DST]), RTA_PAYLOAD(tb[NDA_DST]));
|
||||
if (tb[NDA_LLADDR])
|
||||
memcpy(ndisc_msg->mac_addr, RTA_DATA(tb[NDA_LLADDR]), RTA_PAYLOAD(tb[NDA_LLADDR]));
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "ndisc type %s, state (%04X)(%d), ifindex [%d] (%s), ip %s, mac [%02X:%02X:%02X:%02X:%02X:%02X]",
|
||||
msgtype == RTM_NEWNEIGH ? "New" : "Del", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state),
|
||||
ndm->ndm_ifindex, ndisc_lif->name,
|
||||
show_ipv6_str((char *)ndisc_msg->ipv6_addr),
|
||||
ndisc_msg->mac_addr[0], ndisc_msg->mac_addr[1], ndisc_msg->mac_addr[2], ndisc_msg->mac_addr[3], ndisc_msg->mac_addr[4],
|
||||
ndisc_msg->mac_addr[5]);
|
||||
|
||||
/* Find MLACP itf, member of port-channel */
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
msg = TAILQ_FIRST(&(MLACP(csm).arp_msg_list));
|
||||
TAILQ_REMOVE(&(MLACP(csm).arp_msg_list), msg, tail);
|
||||
arp_msg = (struct ARPMsg *)msg->buf;
|
||||
fprintf(stderr, "\n======== Dequeue ARP ========\n");
|
||||
fprintf(stderr, " Type = [%d]\n", arp_msg->op_type);
|
||||
fprintf(stderr, " State = (%04X)(%d)\n", ndm->ndm_state, fwd_neigh_state_valid(ndm->ndm_state));
|
||||
fprintf(stderr, " ifname = [%s]\n", arp_msg->ifname);
|
||||
fprintf(stderr, " IP = [%s]\n", show_ip_str(arp_msg->ipv4_addr));
|
||||
fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n",
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3],
|
||||
arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
fprintf(stderr, "==============================\n");
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
if (lif_po->type != IF_T_PORT_CHANNEL)
|
||||
continue;
|
||||
|
||||
if (!local_if_is_l3_mode(lif_po))
|
||||
{
|
||||
/* Is the L2 MLAG itf belong to a vlan? */
|
||||
LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next)
|
||||
{
|
||||
if (!(vlan_id_list->vlan_itf && vlan_id_list->vlan_itf->ifindex == ndm->ndm_ifindex))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!vlan_id_list)
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled member port of vlan %s", vlan_id_list->vlan_itf->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is the ND belong to a L3 mode MLAG itf? */
|
||||
if (ndm->ndm_ifindex != lif_po->ifindex)
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled intf %s", lif_po->name);
|
||||
}
|
||||
|
||||
verify_neigh = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (lif_po)
|
||||
break;
|
||||
}
|
||||
|
||||
MLACP(csm).arp_updated = 0;
|
||||
#endif
|
||||
if (!(csm && lif_po))
|
||||
return;
|
||||
if (!verify_neigh)
|
||||
return;
|
||||
|
||||
/* update lif ND */
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
ndisc_info = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
if (memcmp(&ndisc_info->ipv6_addr, &ndisc_msg->ipv6_addr, 16) != 0)
|
||||
continue;
|
||||
|
||||
if (msgtype == RTM_DELNEIGH)
|
||||
{
|
||||
/* delete ND */
|
||||
TAILQ_REMOVE(&MLACP(csm).ndisc_list, msg, tail);
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
msg = NULL;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Delete neighbor %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update ND */
|
||||
if (ndisc_info->op_type != ndisc_info->op_type
|
||||
|| strcmp(ndisc_info->ifname, ndisc_info->ifname) != 0
|
||||
|| memcmp(ndisc_info->mac_addr, ndisc_info->mac_addr, ETHER_ADDR_LEN) != 0)
|
||||
{
|
||||
neigh_update = 1;
|
||||
ndisc_info->op_type = ndisc_msg->op_type;
|
||||
sprintf(ndisc_info->ifname, "%s", ndisc_msg->ifname);
|
||||
memcpy(ndisc_info->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Update neighbor for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg && !neigh_update)
|
||||
return;
|
||||
|
||||
if (msgtype != RTM_DELNEIGH)
|
||||
{
|
||||
/* enquene lif_msg (add) */
|
||||
if (!msg)
|
||||
{
|
||||
ndisc_msg->op_type = NEIGH_SYNC_LIF;
|
||||
if (iccp_csm_init_msg(&msg, (char *)ndisc_msg, msg_len) == 0)
|
||||
{
|
||||
mlacp_enqueue_ndisc(csm, msg);
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "Ndisc-list enqueue: %s, add %s", ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue Ndisc-list: %s, add %s",
|
||||
ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
|
||||
/* enqueue iccp_msg (add) */
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
ndisc_msg->op_type = NEIGH_SYNC_ADD;
|
||||
if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, msg_len) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail);
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue Ndisc[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue Ndisc[ADD] message for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* enqueue iccp_msg (delete) */
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
ndisc_msg->op_type = NEIGH_SYNC_DEL;
|
||||
if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, msg_len) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail);
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue Ndisc[DEL] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Failed to enqueue Ndisc[DEL] message for [%x:%x:%x:%x]", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta, int len, unsigned short flags)
|
||||
{
|
||||
unsigned short type;
|
||||
|
||||
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
|
||||
while (RTA_OK(rta, len))
|
||||
{
|
||||
type = rta->rta_type & ~flags;
|
||||
if ((type <= max) && (!tb[type]))
|
||||
tb[type] = rta;
|
||||
rta = RTA_NEXT(rta, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
||||
{
|
||||
return parse_rtattr_flags(tb, max, rta, len, 0);
|
||||
}
|
||||
|
||||
void ifm_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
|
||||
{
|
||||
while (RTA_OK(rta, len))
|
||||
@ -392,11 +539,14 @@ int do_one_neigh_request(struct nlmsghdr *n)
|
||||
do_arp_learn_from_kernel(ndm, tb, n->nlmsg_type);
|
||||
}
|
||||
|
||||
if (ndm->ndm_family == AF_INET6)
|
||||
{
|
||||
do_ndisc_learn_from_kernel(ndm, tb, n->nlmsg_type);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*Handle arp received from kernel*/
|
||||
static int iccp_arp_valid_handler(struct nl_msg *msg, void *arg)
|
||||
static int iccp_neigh_valid_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
|
||||
@ -405,8 +555,7 @@ static int iccp_arp_valid_handler(struct nl_msg *msg, void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Get kernel arp information during initialization*/
|
||||
int iccp_arp_get_init()
|
||||
int iccp_neigh_get_init()
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct nl_cb *cb;
|
||||
@ -440,7 +589,7 @@ int iccp_arp_get_init()
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_arp_valid_handler, sys);
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_neigh_valid_handler, sys);
|
||||
|
||||
ret = nl_recvmsgs(sys->route_sock, cb);
|
||||
nl_cb_put(cb);
|
||||
@ -485,27 +634,16 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui
|
||||
memset(buf, 0, MAX_BUFSIZE);
|
||||
msg_len = sizeof(struct ARPMsg);
|
||||
arp_msg = (struct ARPMsg*)&buf;
|
||||
arp_msg->op_type = ARP_SYNC_LIF;
|
||||
arp_msg->op_type = NEIGH_SYNC_LIF;
|
||||
sprintf(arp_msg->ifname, "%s", arp_lif->name);
|
||||
memcpy(&arp_msg->ipv4_addr, &addr, 4);
|
||||
memcpy(arp_msg->mac_addr, mac_addr, 6);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ARP ifindex [%d] (%s) ip %s mac [%02X:%02X:%02X:%02X:%02X:%02X]",
|
||||
ifindex, arp_lif->name,
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)),
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
/*Debug*/
|
||||
#if 0
|
||||
/* dump receive kernel ARP req*/
|
||||
fprintf(stderr, "\n======== Kernel ARP Update==========\n");
|
||||
fprintf(stderr, " Type = (New=%d)\n", RTM_NEWNEIGH);
|
||||
fprintf(stderr, " ifindex = [%d] (%s)\n", ifindex, arp_lif->name);
|
||||
fprintf(stderr, " IP = [%s]\n", show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
fprintf(stderr, " MAC = [%02X:%02X:%02X:%02X:%02X:%02X]\n",
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3],
|
||||
arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
fprintf(stderr, "==============================\n");
|
||||
#endif
|
||||
show_ip_str(arp_msg->ipv4_addr),
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4],
|
||||
arp_msg->mac_addr[5]);
|
||||
|
||||
/* Find MLACP itf, member of port-channel*/
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
@ -556,7 +694,7 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui
|
||||
if (iccp_check_if_addr_from_netlink(AF_INET, &addr, arp_lif))
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ARP %s is identical with the ip address of interface %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)), arp_lif->name);
|
||||
show_ip_str(arp_msg->ipv4_addr), arp_lif->name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -576,8 +714,9 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui
|
||||
arp_info->op_type = arp_msg->op_type;
|
||||
sprintf(arp_info->ifname, "%s", arp_msg->ifname);
|
||||
memcpy(arp_info->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Update ARP for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Update ARP for %s by ARP reply, intf %s mac [%02X:%02X:%02X:%02X:%02X:%02X]",
|
||||
show_ip_str(arp_msg->ipv4_addr), arp_msg->ifname,
|
||||
arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2], arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -585,36 +724,196 @@ void do_arp_update_from_reply_packet(unsigned int ifindex, unsigned int addr, ui
|
||||
/* enquene lif_msg (add)*/
|
||||
if (!msg)
|
||||
{
|
||||
arp_msg->op_type = ARP_SYNC_LIF;
|
||||
arp_msg->op_type = NEIGH_SYNC_LIF;
|
||||
if (iccp_csm_init_msg(&msg, (char*)arp_msg, msg_len) == 0)
|
||||
{
|
||||
mlacp_enqueue_arp(csm, msg);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "ARP-list enqueue: %s, add %s",
|
||||
arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP-list: %s, add %s",
|
||||
arp_msg->ifname, show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
arp_msg->ifname, show_ip_str(arp_msg->ipv4_addr));
|
||||
}
|
||||
|
||||
/* enqueue iccp_msg (add)*/
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
arp_msg->op_type = ARP_SYNC_ADD;
|
||||
arp_msg->op_type = NEIGH_SYNC_ADD;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, msg_len) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).arp_msg_list), msg_send, tail);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ARP[ADD] for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] message for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
show_ip_str(arp_msg->ipv4_addr));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void do_ndisc_update_from_reply_packet(unsigned int ifindex, char *ipv6_addr, uint8_t mac_addr[ETHER_ADDR_LEN])
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct CSM *csm = NULL;
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *ndisc_msg = NULL, *ndisc_info = NULL;
|
||||
struct VLAN_ID *vlan_id_list = NULL;
|
||||
struct Msg *msg_send = NULL;
|
||||
char mac_str[18] = "";
|
||||
uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
char buf[MAX_BUFSIZE];
|
||||
size_t msg_len = 0;
|
||||
|
||||
struct LocalInterface *lif_po = NULL, *ndisc_lif = NULL;
|
||||
|
||||
int verify_ndisc = 0;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
return;
|
||||
|
||||
/* Find local itf */
|
||||
if (!(ndisc_lif = local_if_find_by_ifindex(ifindex)))
|
||||
return;
|
||||
|
||||
sprintf(mac_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]);
|
||||
|
||||
/* create Ndisc msg */
|
||||
memset(buf, 0, MAX_BUFSIZE);
|
||||
msg_len = sizeof(struct NDISCMsg);
|
||||
ndisc_msg = (struct NDISCMsg *)&buf;
|
||||
ndisc_msg->op_type = NEIGH_SYNC_LIF;
|
||||
sprintf(ndisc_msg->ifname, "%s", ndisc_lif->name);
|
||||
memcpy((char *)ndisc_msg->ipv6_addr, ipv6_addr, 16);
|
||||
memcpy(ndisc_msg->mac_addr, mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "nd ifindex [%d] (%s) ip %s mac %s",
|
||||
ifindex, ndisc_lif->name, show_ipv6_str(ipv6_addr), mac_str);
|
||||
|
||||
/* Find MLACP itf, member of port-channel */
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
{
|
||||
LIST_FOREACH(lif_po, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
if (lif_po->type != IF_T_PORT_CHANNEL)
|
||||
continue;
|
||||
|
||||
if (!local_if_is_l3_mode(lif_po))
|
||||
{
|
||||
/* Is the L2 MLAG itf belong to a vlan? */
|
||||
LIST_FOREACH(vlan_id_list, &(lif_po->vlan_list), port_next)
|
||||
{
|
||||
if (!(vlan_id_list->vlan_itf && vlan_id_list->vlan_itf->ifindex == ifindex))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!vlan_id_list)
|
||||
continue;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled port %s of vlan %s", lif_po->name, vlan_id_list->vlan_itf->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is the ND belong to a L3 mode MLAG itf? */
|
||||
if (ifindex != lif_po->ifindex)
|
||||
continue;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ND is from mclag enabled port %s", lif_po->name);
|
||||
}
|
||||
|
||||
verify_ndisc = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (lif_po)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(csm && lif_po))
|
||||
return;
|
||||
if (!verify_ndisc)
|
||||
return;
|
||||
|
||||
if (iccp_check_if_addr_from_netlink(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, ndisc_lif))
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "NA %s is identical with the ipv6 address of interface %s",
|
||||
show_ipv6_str((char *)ndisc_msg->ipv6_addr), ndisc_lif->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* update lif ND */
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
ndisc_info = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
if (memcmp((char *)ndisc_info->ipv6_addr, (char *)ndisc_msg->ipv6_addr, 16) != 0)
|
||||
continue;
|
||||
|
||||
/* If MAC addr is NULL, use the old one */
|
||||
if (memcmp(mac_addr, null_mac, ETHER_ADDR_LEN) == 0)
|
||||
{
|
||||
memcpy(ndisc_msg->mac_addr, ndisc_info->mac_addr, ETHER_ADDR_LEN);
|
||||
sprintf(mac_str, "%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]);
|
||||
}
|
||||
|
||||
/* update ND */
|
||||
if (ndisc_info->op_type != ndisc_msg->op_type
|
||||
|| strcmp(ndisc_info->ifname, ndisc_msg->ifname) != 0
|
||||
|| memcmp(ndisc_info->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN) != 0)
|
||||
{
|
||||
ndisc_info->op_type = ndisc_msg->op_type;
|
||||
sprintf(ndisc_info->ifname, "%s", ndisc_msg->ifname);
|
||||
memcpy(ndisc_info->mac_addr, ndisc_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Update ND for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* enquene lif_msg (add) */
|
||||
if (!msg)
|
||||
{
|
||||
/* If MAC addr is NULL, and same ipv6 item is not exist in ndisc_list */
|
||||
if (memcmp(mac_addr, null_mac, ETHER_ADDR_LEN) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ndisc_msg->op_type = NEIGH_SYNC_LIF;
|
||||
if (iccp_csm_init_msg(&msg, (char *)ndisc_msg, msg_len) == 0)
|
||||
{
|
||||
mlacp_enqueue_ndisc(csm, msg);
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "NDISC-list enqueue: %s, add %s", ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue NDISC-list: %s, add %s", ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
|
||||
if (iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, 1, ndisc_msg->mac_addr, ndisc_msg->ifname) < 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to add ND entry(%s, %s, %s) to kernel",
|
||||
ndisc_msg->ifname, show_ipv6_str((char *)ndisc_msg->ipv6_addr), mac_str);
|
||||
return;
|
||||
}
|
||||
|
||||
/* enqueue iccp_msg (add) */
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
ndisc_msg->op_type = NEIGH_SYNC_ADD;
|
||||
if (iccp_csm_init_msg(&msg_send, (char *)ndisc_msg, msg_len) == 0)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_msg_list), msg_send, tail);
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ND[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr)); */
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ND[ADD] message for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
void iccp_from_netlink_port_state_handler( char * ifname, int state)
|
||||
{
|
||||
struct CSM *csm = NULL;
|
||||
@ -656,29 +955,6 @@ void iccp_from_netlink_port_state_handler( char * ifname, int state)
|
||||
return;
|
||||
}
|
||||
|
||||
int parse_rtattr_flags(struct rtattr *tb[], int max, struct rtattr *rta,
|
||||
int len, unsigned short flags)
|
||||
{
|
||||
unsigned short type;
|
||||
|
||||
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
|
||||
|
||||
while (RTA_OK(rta, len))
|
||||
{
|
||||
type = rta->rta_type & ~flags;
|
||||
if ((type <= max) && (!tb[type]))
|
||||
tb[type] = rta;
|
||||
rta = RTA_NEXT(rta, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
|
||||
{
|
||||
return parse_rtattr_flags(tb, max, rta, len, 0);
|
||||
}
|
||||
|
||||
void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n)
|
||||
{
|
||||
struct LocalInterface *lif = NULL;
|
||||
@ -759,4 +1035,4 @@ void iccp_parse_if_vlan_info_from_netlink(struct nlmsghdr *n)
|
||||
|
||||
n = NLMSG_NEXT(n, msglen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,15 +35,18 @@
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/types.h>
|
||||
#include <netlink/route/link.h>
|
||||
#include <netlink/route/route.h>
|
||||
#include <netlink/route/neighbour.h>
|
||||
#include <netlink/route/link/bridge.h>
|
||||
#include <netlink/cli/utils.h>
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/if_team.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/in6.h>
|
||||
|
||||
#include "../include/system.h"
|
||||
#include "../include/iccp_ifm.h"
|
||||
@ -53,6 +56,8 @@
|
||||
#include "../include/scheduler.h"
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
#include "../include/msg_format.h"
|
||||
#include "../include/iccp_netlink.h"
|
||||
|
||||
/**
|
||||
* SECTION: Netlink helpers
|
||||
*/
|
||||
@ -324,13 +329,6 @@ int iccp_get_portchannel_member_list_handler(struct nl_msg *msg, void * arg)
|
||||
{
|
||||
memset(local_if->portchannel_member_buf, 0, 512);
|
||||
memcpy(local_if->portchannel_member_buf, temp_buf, sizeof(local_if->portchannel_member_buf) - 1);
|
||||
#if 0
|
||||
if (MLACP(csm).current_state == MLACP_STATE_EXCHANGE)
|
||||
{
|
||||
/*peerlink portchannel member changed*/
|
||||
update_peerlink_isolate_from_all_csm_lif(csm);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -491,7 +489,7 @@ void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr )
|
||||
dst_len = strlen(mac_addr);
|
||||
memcpy(sub_msg->data, mac_addr, dst_len);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "If name %s ip %s mac %s", lif->name, show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data);
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "If name %s ip %s mac %s", lif->name, show_ip_str(htonl(lif->ipv4_addr)), sub_msg->data);
|
||||
|
||||
sub_msg->op_len = dst_len;
|
||||
msg_hdr->len += sizeof(mclag_sub_option_hdr_t);
|
||||
@ -504,6 +502,51 @@ void iccp_set_interface_ipadd_mac(struct LocalInterface *lif, char * mac_addr )
|
||||
return;
|
||||
}
|
||||
|
||||
int iccp_netlink_if_startup_set(uint32_t ifindex)
|
||||
{
|
||||
struct rtnl_link *link;
|
||||
int err;
|
||||
struct System *sys = NULL;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
return MCLAG_ERROR;
|
||||
|
||||
link = rtnl_link_alloc();
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
|
||||
rtnl_link_set_ifindex(link, ifindex);
|
||||
rtnl_link_set_flags(link, IFF_UP);
|
||||
|
||||
err = rtnl_link_change(sys->route_sock, link, link, 0);
|
||||
|
||||
errout:
|
||||
rtnl_link_put(link);
|
||||
return err;
|
||||
}
|
||||
|
||||
int iccp_netlink_if_shutdown_set(uint32_t ifindex)
|
||||
{
|
||||
struct rtnl_link *link;
|
||||
int err;
|
||||
struct System *sys = NULL;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
return MCLAG_ERROR;
|
||||
|
||||
link = rtnl_link_alloc();
|
||||
if (!link)
|
||||
return -ENOMEM;
|
||||
|
||||
rtnl_link_set_ifindex(link, ifindex);
|
||||
rtnl_link_unset_flags(link, IFF_UP);
|
||||
|
||||
err = rtnl_link_change(sys->route_sock, link, link, 0);
|
||||
|
||||
errout:
|
||||
rtnl_link_put(link);
|
||||
return err;
|
||||
}
|
||||
void update_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
{
|
||||
struct CSM* csm;
|
||||
@ -535,7 +578,7 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
/*Backup old sysmac*/
|
||||
memcpy(lif_po->mac_addr_ori, lif_po->mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__,
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__,
|
||||
"%s Change the system-id of %s from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].",
|
||||
(csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active",
|
||||
lif_po->name, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5],
|
||||
@ -546,6 +589,10 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", lif_po->name, ret);
|
||||
}
|
||||
|
||||
/* Refresh link local address according the new MAC */
|
||||
iccp_netlink_if_shutdown_set(lif_po->ifindex);
|
||||
iccp_netlink_if_startup_set(lif_po->ifindex);
|
||||
}
|
||||
|
||||
/*Set portchannel ip mac */
|
||||
@ -576,8 +623,12 @@ void update_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", vlan->vlan_itf->name, ret);
|
||||
}
|
||||
|
||||
iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr );
|
||||
|
||||
/* Refresh link local address according the new MAC */
|
||||
iccp_netlink_if_shutdown_set(vlan->vlan_itf->ifindex);
|
||||
iccp_netlink_if_startup_set(vlan->vlan_itf->ifindex);
|
||||
|
||||
iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr);
|
||||
memcpy(vlan->vlan_itf->l3_mac_addr, MLACP(csm).remote_system.system_id, ETHER_ADDR_LEN);
|
||||
}
|
||||
}
|
||||
@ -611,7 +662,7 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
/*Recover mac to origin mac, it is the 'mac' value in 'localhost' currently*/
|
||||
if (memcmp( lif_po->mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN) != 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__,
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__,
|
||||
"%s Recover the system-id of %s from [%02X:%02X:%02X:%02X:%02X:%02X] to [%02X:%02X:%02X:%02X:%02X:%02X].",
|
||||
(csm->role_type == STP_ROLE_STANDBY) ? "Standby" : "Active",
|
||||
lif_po->name, lif_po->mac_addr[0], lif_po->mac_addr[1], lif_po->mac_addr[2], lif_po->mac_addr[3], lif_po->mac_addr[4], lif_po->mac_addr[5],
|
||||
@ -622,6 +673,10 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", lif_po->name, ret);
|
||||
}
|
||||
|
||||
/* Refresh link local address according the new MAC */
|
||||
iccp_netlink_if_shutdown_set(lif_po->ifindex);
|
||||
iccp_netlink_if_startup_set(lif_po->ifindex);
|
||||
}
|
||||
|
||||
/*Set portchannel ip mac */
|
||||
@ -648,6 +703,10 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Set %s mac error, ret = %d", vlan->vlan_itf->name, ret);
|
||||
}
|
||||
|
||||
/* Refresh link local address according the new MAC */
|
||||
iccp_netlink_if_shutdown_set(vlan->vlan_itf->ifindex);
|
||||
iccp_netlink_if_startup_set(vlan->vlan_itf->ifindex);
|
||||
|
||||
iccp_set_interface_ipadd_mac(vlan->vlan_itf, macaddr);
|
||||
memcpy(vlan->vlan_itf->l3_mac_addr, MLACP(csm).system_id, ETHER_ADDR_LEN);
|
||||
}
|
||||
@ -657,6 +716,80 @@ void recover_if_ipmac_on_standby(struct LocalInterface* lif_po)
|
||||
return;
|
||||
}
|
||||
|
||||
int iccp_netlink_neighbor_request(int family, uint8_t *addr, int add, uint8_t *mac, char *portname)
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
struct rtnl_neigh *neigh = NULL;
|
||||
struct nl_addr *nl_addr_mac = NULL;
|
||||
struct nl_addr *nl_addr_dst = NULL;
|
||||
struct LocalInterface *lif = NULL;
|
||||
struct nl_cache *link_cache;
|
||||
char mac_str[18] = "";
|
||||
int err = 0;
|
||||
|
||||
if (!(sys = system_get_instance()))
|
||||
return MCLAG_ERROR;
|
||||
|
||||
lif = local_if_find_by_name(portname);
|
||||
if (!lif)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
neigh = rtnl_neigh_alloc();
|
||||
if (!neigh)
|
||||
{
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "Unable to allocate neighbour object");
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Notify kernel %s %s entry(ip:%s, mac:%s, intf:%s)",
|
||||
add ? "add" : "del", (family == AF_INET) ? "ARP" : "ND",
|
||||
(family == AF_INET) ? show_ip_str(*((int *)addr)) : show_ipv6_str(addr), mac_str, portname);
|
||||
|
||||
nl_addr_mac = nl_addr_build(AF_LLC, (void *)mac, ETHER_ADDR_LEN);
|
||||
if (!nl_addr_mac)
|
||||
{
|
||||
err = MCLAG_ERROR;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (family == AF_INET)
|
||||
nl_addr_dst = nl_addr_build(family, (void *)addr, 4);
|
||||
else
|
||||
nl_addr_dst = nl_addr_build(family, (void *)addr, 16);
|
||||
|
||||
if (!nl_addr_dst)
|
||||
{
|
||||
err = MCLAG_ERROR;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
rtnl_neigh_set_lladdr(neigh, nl_addr_mac);
|
||||
rtnl_neigh_set_dst(neigh, nl_addr_dst);
|
||||
rtnl_neigh_set_ifindex(neigh, lif->ifindex);
|
||||
rtnl_neigh_set_state(neigh, NUD_REACHABLE);
|
||||
|
||||
if (add)
|
||||
{
|
||||
if ((err = rtnl_neigh_add(sys->route_sock, neigh, NLM_F_REPLACE | NLM_F_CREATE)) < 0)
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Add %s (ip:%s, mac:%s) error, err = %d", (family == AF_INET) ? "ARP" : "ND",
|
||||
(family == AF_INET) ? show_ip_str(*((int *)addr)) : show_ipv6_str(addr), mac_str, err);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((err = rtnl_neigh_delete(sys->route_sock, neigh, 0)) < 0)
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Del %s (ip:%s, mac:%s) error, err = %d", (family == AF_INET) ? "ARP" : "ND",
|
||||
(family == AF_INET) ? show_ip_str(*((int *)addr)) : show_ipv6_str(addr), mac_str, err);
|
||||
}
|
||||
|
||||
errout:
|
||||
nl_addr_put(nl_addr_mac);
|
||||
nl_addr_put(nl_addr_dst);
|
||||
rtnl_neigh_put(neigh);
|
||||
return err;
|
||||
}
|
||||
|
||||
void iccp_event_handler_obj_input_newlink(struct nl_object *obj, void *arg)
|
||||
{
|
||||
struct rtnl_link *link;
|
||||
@ -789,6 +922,103 @@ void iccp_event_handler_obj_input_dellink(struct nl_object *obj, void *arg)
|
||||
return;
|
||||
}
|
||||
|
||||
void iccp_event_handler_obj_input_newaddr(struct nl_object *obj, void *arg)
|
||||
{
|
||||
struct rtnl_addr *addr;
|
||||
struct nl_addr *nl_addr;
|
||||
struct LocalInterface *lif;
|
||||
uint32_t ifindex;
|
||||
char addrStr[65] = { 0 };
|
||||
char addr_null[16] = { 0 };
|
||||
addr = (struct rtnl_addr *)obj;
|
||||
|
||||
ifindex = rtnl_addr_get_ifindex(addr);
|
||||
nl_addr = rtnl_addr_get_local(addr);
|
||||
|
||||
if (!(lif = local_if_find_by_ifindex(ifindex)))
|
||||
return;
|
||||
|
||||
if (rtnl_addr_get_family(addr) == AF_INET)
|
||||
{
|
||||
lif->ipv4_addr = *(uint32_t *) nl_addr_get_binary_addr(nl_addr);
|
||||
lif->prefixlen = nl_addr_get_prefixlen(nl_addr);
|
||||
lif->l3_mode = 1;
|
||||
lif->port_config_sync = 1;
|
||||
if (memcmp((char *)lif->ipv6_addr, addr_null, 16) == 0)
|
||||
update_if_ipmac_on_standby(lif);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Ifname %s index %d address %s", lif->name, lif->ifindex, show_ip_str(lif->ipv4_addr));
|
||||
}
|
||||
else if (rtnl_addr_get_family(addr) == AF_INET6)
|
||||
{
|
||||
if (memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "FE80", 4) == 0
|
||||
|| memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "fe80", 4) == 0)
|
||||
return;
|
||||
|
||||
memcpy((char *)lif->ipv6_addr, nl_addr_get_binary_addr(nl_addr), 16);
|
||||
lif->prefixlen = nl_addr_get_prefixlen(nl_addr);
|
||||
lif->l3_mode = 1;
|
||||
lif->port_config_sync = 1;
|
||||
if (lif->ipv4_addr == 0)
|
||||
update_if_ipmac_on_standby(lif);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Ifname %s index %d address %s", lif->name, lif->ifindex, show_ipv6_str((char *)lif->ipv6_addr));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void iccp_event_handler_obj_input_deladdr(struct nl_object *obj, void *arg)
|
||||
{
|
||||
struct rtnl_addr *addr;
|
||||
struct nl_addr *nl_addr;
|
||||
struct LocalInterface *lif;
|
||||
uint32_t ifindex;
|
||||
char addr_null[16] = { 0 };
|
||||
|
||||
addr = (struct rtnl_addr *)obj;
|
||||
|
||||
ifindex = rtnl_addr_get_ifindex(addr);
|
||||
nl_addr = rtnl_addr_get_local(addr);
|
||||
|
||||
if (!(lif = local_if_find_by_ifindex(ifindex)))
|
||||
return;
|
||||
|
||||
if (rtnl_addr_get_family(addr) == AF_INET)
|
||||
{
|
||||
lif->ipv4_addr = 0;
|
||||
lif->prefixlen = 0;
|
||||
}
|
||||
else if (rtnl_addr_get_family(addr) == AF_INET6)
|
||||
{
|
||||
if (memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "FE80", 4) == 0
|
||||
|| memcmp(show_ipv6_str((char *)nl_addr_get_binary_addr(nl_addr)), "fe80", 4) == 0)
|
||||
return;
|
||||
|
||||
memset((char *)lif->ipv6_addr, 0, 16);
|
||||
lif->prefixlen_v6 = 0;
|
||||
}
|
||||
|
||||
if (lif->ipv4_addr == 0 && memcmp((char *)lif->ipv6_addr, addr_null, 16) == 0)
|
||||
{
|
||||
lif->l3_mode = 0;
|
||||
memset(lif->l3_mac_addr, 0, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int iccp_addr_valid_handler(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(msg);
|
||||
unsigned int event = 0;
|
||||
if (nlh->nlmsg_type != RTM_NEWADDR)
|
||||
return 0;
|
||||
|
||||
if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newaddr, &event) < 0)
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Unknown message type.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInterface *lif)
|
||||
{
|
||||
struct
|
||||
@ -893,61 +1123,6 @@ int iccp_check_if_addr_from_netlink(int family, uint8_t *addr, struct LocalInter
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iccp_local_if_addr_update(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
int len;
|
||||
struct ifaddrmsg *ifa;
|
||||
struct LocalInterface *lif;
|
||||
|
||||
struct nlmsghdr *n = nlmsg_hdr(msg);
|
||||
|
||||
if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
|
||||
return 0;
|
||||
|
||||
ifa = NLMSG_DATA(n);
|
||||
|
||||
if (ifa->ifa_family != AF_INET )
|
||||
return 0;
|
||||
|
||||
lif = local_if_find_by_ifindex(ifa->ifa_index);
|
||||
if (!lif)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (n->nlmsg_type == RTM_DELADDR)
|
||||
{
|
||||
lif->ipv4_addr = 0;
|
||||
lif->prefixlen = 0;
|
||||
lif->l3_mode = 0;
|
||||
memset(lif->l3_mac_addr, 0, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
len = n->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg));
|
||||
if (len < 0)
|
||||
return 0;
|
||||
|
||||
struct rtattr *rth = IFA_RTA(ifa);
|
||||
int rtl = IFA_PAYLOAD(n);
|
||||
|
||||
while (rtl && RTA_OK(rth, rtl))
|
||||
{
|
||||
if (rth->rta_type == IFA_ADDRESS)
|
||||
{
|
||||
uint32_t ipaddr = ntohl(*((uint32_t *)RTA_DATA(rth)));
|
||||
lif->ipv4_addr = ipaddr;
|
||||
lif->prefixlen = ifa->ifa_prefixlen;
|
||||
lif->l3_mode = 1;
|
||||
lif->port_config_sync = 1;
|
||||
update_if_ipmac_on_standby(lif);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "If name %s index %d ip %s", lif->name, lif->ifindex, show_ip_str(htonl(lif->ipv4_addr)));
|
||||
}
|
||||
rth = RTA_NEXT(rth, rtl);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iccp_sys_local_if_list_get_addr()
|
||||
{
|
||||
struct System *sys = NULL;
|
||||
@ -983,7 +1158,7 @@ int iccp_sys_local_if_list_get_addr()
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_local_if_addr_update, sys);
|
||||
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, iccp_addr_valid_handler, sys);
|
||||
ret = nl_recvmsgs(sys->route_sock, cb);
|
||||
nl_cb_put(cb);
|
||||
if (ret < 0)
|
||||
@ -1022,9 +1197,13 @@ static int iccp_route_event_handler(struct nl_msg *msg, void *arg)
|
||||
break;
|
||||
|
||||
case RTM_NEWADDR:
|
||||
iccp_local_if_addr_update(msg, NULL);
|
||||
if (nl_msg_parse(msg, &iccp_event_handler_obj_input_newaddr, NULL) < 0)
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_NEWADDR).");
|
||||
break;
|
||||
case RTM_DELADDR:
|
||||
if (nl_msg_parse(msg, &iccp_event_handler_obj_input_deladdr, NULL) < 0)
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Unknown message type(RTM_DELADDR).");
|
||||
break;
|
||||
|
||||
default:
|
||||
return NL_OK;
|
||||
}
|
||||
@ -1048,6 +1227,53 @@ static int iccp_genric_event_handler(struct nl_msg *msg, void *arg)
|
||||
return NL_SKIP;
|
||||
}
|
||||
|
||||
int iccp_make_nd_socket(void)
|
||||
{
|
||||
int sock;
|
||||
int ret;
|
||||
int val;
|
||||
struct icmp6_filter filter;
|
||||
|
||||
sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to create nd socket");
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
val = 1;
|
||||
#ifdef IPV6_RECVPKTINFO /* 2292bis-01 */
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)) < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to set IPV6_RECVPKTINFO for nd socket");
|
||||
close(sock);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
#else /* RFC2292 */
|
||||
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &val, sizeof(val)) < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to set IPV6_PKTINFO for nd socket");
|
||||
close(sock);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
ICMP6_FILTER_SETBLOCKALL(&filter);
|
||||
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filter);
|
||||
|
||||
ret = setsockopt(sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(struct icmp6_filter));
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to set ICMP6_FILTER");
|
||||
close(sock);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
/*init netlink socket*/
|
||||
int iccp_system_init_netlink_socket()
|
||||
{
|
||||
@ -1135,45 +1361,7 @@ int iccp_system_init_netlink_socket()
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to set buffer size of netlink event sock.");
|
||||
goto err_return;
|
||||
}
|
||||
#if 0
|
||||
sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME);
|
||||
|
||||
while (sys->family < 0)
|
||||
{
|
||||
sleep(1);
|
||||
log_err_period++;
|
||||
/*If no portchannel configuration, teamd will not started, genl_ctrl_resolve() will return <0 forever */
|
||||
/*Only log error message 5 times*/
|
||||
if (log_err_period == 1 && log_err_time < 5)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink family. %d of TEAM_GENL_NAME %s ", sys->family, TEAM_GENL_NAME);
|
||||
log_err_time++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*Log error message every 30s per time*/
|
||||
if (log_err_period == 30)
|
||||
log_err_period = 0;
|
||||
}
|
||||
|
||||
sys->family = genl_ctrl_resolve(sys->genric_sock, TEAM_GENL_NAME);
|
||||
}
|
||||
|
||||
grp_id = genl_ctrl_resolve_grp(sys->genric_sock, TEAM_GENL_NAME,
|
||||
TEAM_GENL_CHANGE_EVENT_MC_GRP_NAME);
|
||||
if (grp_id < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to resolve netlink multicast groups. %d", grp_id);
|
||||
goto err_return;
|
||||
}
|
||||
|
||||
err = nl_socket_add_membership(sys->genric_event_sock, grp_id);
|
||||
if (err < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership.");
|
||||
goto err_return;
|
||||
}
|
||||
#endif
|
||||
nl_socket_disable_seq_check(sys->genric_event_sock);
|
||||
nl_socket_modify_cb(sys->genric_event_sock, NL_CB_VALID, NL_CB_CUSTOM,
|
||||
iccp_genric_event_handler, sys);
|
||||
@ -1202,8 +1390,13 @@ int iccp_system_init_netlink_socket()
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership.");
|
||||
goto err_return;
|
||||
}
|
||||
|
||||
/*receive arp packet socket*/
|
||||
err = nl_socket_add_membership(sys->route_event_sock, RTNLGRP_IPV6_IFADDR);
|
||||
if (err < 0)
|
||||
{
|
||||
ICCPD_LOG_ERR(__FUNCTION__, "Failed to add netlink membership.");
|
||||
goto err_return;
|
||||
}
|
||||
/* receive arp packet socket */
|
||||
sys->arp_receive_fd = socket(PF_PACKET, SOCK_DGRAM, 0);
|
||||
if (sys->arp_receive_fd < 0)
|
||||
{
|
||||
@ -1225,6 +1418,13 @@ int iccp_system_init_netlink_socket()
|
||||
}
|
||||
}
|
||||
|
||||
sys->ndisc_receive_fd = iccp_make_nd_socket();
|
||||
|
||||
if (sys->ndisc_receive_fd < 0)
|
||||
{
|
||||
goto err_return;
|
||||
}
|
||||
|
||||
goto succes_return;
|
||||
|
||||
err_return:
|
||||
@ -1295,6 +1495,11 @@ static int iccp_get_receive_arp_packet_sock_fd(struct System *sys)
|
||||
return sys->arp_receive_fd;
|
||||
}
|
||||
|
||||
static int iccp_get_receive_ndisc_packet_sock_fd(struct System *sys)
|
||||
{
|
||||
return sys->ndisc_receive_fd;
|
||||
}
|
||||
|
||||
static int iccp_receive_arp_packet_handler(struct System *sys)
|
||||
{
|
||||
unsigned char buf[1024];
|
||||
@ -1328,7 +1533,100 @@ static int iccp_receive_arp_packet_handler(struct System *sys)
|
||||
memcpy(mac_addr, (char*)(a + 1), ETHER_ADDR_LEN);
|
||||
memcpy(&addr, (char*)(a + 1) + a->ar_hln, 4);
|
||||
|
||||
do_arp_update_from_reply_packet(ifindex, ntohl(addr), mac_addr);
|
||||
do_arp_update_from_reply_packet(ifindex, addr, mac_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iccp_receive_ndisc_packet_handler(struct System *sys)
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
uint8_t adata[1024];
|
||||
struct sockaddr_in6 from;
|
||||
unsigned int ifindex = 0;
|
||||
struct msghdr msg;
|
||||
struct iovec iov;
|
||||
struct cmsghdr *cmsgptr;
|
||||
struct nd_msg *ndmsg = NULL;
|
||||
struct nd_opt_hdr *nd_opt = NULL;
|
||||
struct in6_addr target;
|
||||
uint8_t mac_addr[ETHER_ADDR_LEN];
|
||||
int8_t *opt = NULL;
|
||||
int opt_len = 0, l = 0;
|
||||
int len;
|
||||
|
||||
memset(mac_addr, 0, ETHER_ADDR_LEN);
|
||||
|
||||
/* Fill in message and iovec. */
|
||||
msg.msg_name = (void *)(&from);
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = (void *)adata;
|
||||
msg.msg_controllen = sizeof adata;
|
||||
iov.iov_base = buf;
|
||||
iov.iov_len = 4096;
|
||||
|
||||
len = recvmsg(sys->ndisc_receive_fd, &msg, 0);
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Ndisc recvmsg error!");
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
|
||||
{
|
||||
/* I want interface index which this packet comes from. */
|
||||
if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO)
|
||||
{
|
||||
struct in6_pktinfo *ptr;
|
||||
|
||||
ptr = (struct in6_pktinfo *)CMSG_DATA(cmsgptr);
|
||||
ifindex = ptr->ipi6_ifindex;
|
||||
}
|
||||
}
|
||||
|
||||
ndmsg = (struct nd_msg *)buf;
|
||||
|
||||
if (ndmsg->icmph.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT)
|
||||
return 0;
|
||||
|
||||
memcpy((char *)(&target), (char *)(&ndmsg->target), sizeof(struct in6_addr));
|
||||
|
||||
opt = (char *)ndmsg->opt;
|
||||
|
||||
opt_len = len - sizeof(struct nd_msg);
|
||||
|
||||
if (opt && opt_len > 0)
|
||||
{
|
||||
while (opt_len)
|
||||
{
|
||||
if (opt_len < sizeof(struct nd_opt_hdr))
|
||||
return 0;
|
||||
|
||||
nd_opt = (struct nd_opt_hdr *)opt;
|
||||
|
||||
l = nd_opt->nd_opt_len << 3;
|
||||
|
||||
if (l == 0)
|
||||
return 0;
|
||||
|
||||
if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR)
|
||||
{
|
||||
memcpy(mac_addr, (char *)((char *)nd_opt + sizeof(struct nd_opt_hdr)), ETHER_ADDR_LEN);
|
||||
break;
|
||||
}
|
||||
|
||||
opt += l;
|
||||
opt_len -= l;
|
||||
}
|
||||
}
|
||||
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "Recv na pkt(%s,%02X:%02X:%02X:%02X:%02X:%02X)!", show_ipv6_str((char *)&target), mac_addr[0], mac_addr[1],
|
||||
mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); */
|
||||
do_ndisc_update_from_reply_packet(ifindex, (char *)&target, mac_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1412,7 +1710,11 @@ static const struct iccp_eventfd iccp_eventfds[] = {
|
||||
{
|
||||
.get_fd = iccp_get_receive_arp_packet_sock_fd,
|
||||
.event_handler = iccp_receive_arp_packet_handler,
|
||||
}
|
||||
},
|
||||
{
|
||||
.get_fd = iccp_get_receive_ndisc_packet_sock_fd,
|
||||
.event_handler = iccp_receive_ndisc_packet_handler,
|
||||
}
|
||||
};
|
||||
|
||||
/* \cond HIDDEN_SYMBOLS */
|
||||
|
@ -65,6 +65,14 @@ static struct command_type command_types[] =
|
||||
.enca_msg = mclagdctl_enca_dump_arp,
|
||||
.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,
|
||||
@ -290,6 +298,24 @@ int mclagdctl_enca_dump_arp(char *msg, int mclag_id, int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mclagdctl_enca_dump_ndisc(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_NDISC;
|
||||
req.mclag_id = mclag_id;
|
||||
memcpy((struct mclagdctl_req_hdr *)msg, &req, sizeof(struct mclagdctl_req_hdr));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mclagdctl_parse_dump_arp(char *msg, int data_len)
|
||||
{
|
||||
struct mclagd_arp_msg * arp_info = NULL;
|
||||
@ -322,6 +348,38 @@ int mclagdctl_parse_dump_arp(char *msg, int data_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mclagdctl_parse_dump_ndisc(char *msg, int data_len)
|
||||
{
|
||||
struct mclagd_ndisc_msg *ndisc_info = NULL;
|
||||
int len = 0;
|
||||
int count = 0;
|
||||
|
||||
fprintf(stdout, "%-6s", "No.");
|
||||
fprintf(stdout, "%-52s", "IPv6");
|
||||
fprintf(stdout, "%-20s", "MAC");
|
||||
fprintf(stdout, "%-20s", "DEV");
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
len = sizeof(struct mclagd_ndisc_msg);
|
||||
|
||||
for (; data_len >= len; data_len -= len, count++)
|
||||
{
|
||||
ndisc_info = (struct mclagd_ndisc_msg *)(msg + len * count);
|
||||
|
||||
fprintf(stdout, "%-6d", count + 1);
|
||||
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]);
|
||||
fprintf(stdout, " ");
|
||||
fprintf(stdout, "%-20s", ndisc_info->ifname);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv)
|
||||
{
|
||||
struct mclagdctl_req_hdr req;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#define MCLAGDCTL_MAX_L_PORT_NANE 32
|
||||
#define MCLAGDCTL_INET_ADDR_LEN 32
|
||||
#define MCLAGDCTL_INET6_ADDR_LEN 64
|
||||
#define MCLAGDCTL_ETHER_ADDR_LEN 6
|
||||
#define MCLAGDCTL_PORT_MEMBER_BUF_LEN 512
|
||||
#define ETHER_ADDR_STR_LEN 18
|
||||
@ -62,6 +63,7 @@ enum mclagdctl_notify_peer_type
|
||||
INFO_TYPE_NONE = 0,
|
||||
INFO_TYPE_DUMP_STATE,
|
||||
INFO_TYPE_DUMP_ARP,
|
||||
INFO_TYPE_DUMP_NDISC,
|
||||
INFO_TYPE_DUMP_MAC,
|
||||
INFO_TYPE_DUMP_LOCAL_PORTLIST,
|
||||
INFO_TYPE_DUMP_PEER_PORTLIST,
|
||||
@ -137,6 +139,14 @@ struct mclagd_arp_msg
|
||||
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
struct mclagd_ndisc_msg
|
||||
{
|
||||
char op_type;
|
||||
char ifname[MCLAGDCTL_MAX_L_PORT_NANE];
|
||||
char ipv6_addr[MCLAGDCTL_INET6_ADDR_LEN];
|
||||
unsigned char mac_addr[MCLAGDCTL_ETHER_ADDR_LEN];
|
||||
};
|
||||
|
||||
struct mclagd_mac_msg
|
||||
{
|
||||
unsigned char op_type;/*add or del*/
|
||||
@ -186,7 +196,9 @@ struct mclagd_peer_if
|
||||
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);
|
||||
extern int mclagdctl_enca_dump_ndisc(char *msg, int mclag_id, int argc, char **argv);
|
||||
extern int mclagdctl_parse_dump_arp(char *msg, int data_len);
|
||||
extern int mclagdctl_parse_dump_ndisc(char *msg, int data_len);
|
||||
extern int mclagdctl_enca_dump_mac(char *msg, int mclag_id, int argc, char **argv);
|
||||
extern int mclagdctl_parse_dump_mac(char *msg, int data_len);
|
||||
extern int mclagdctl_enca_dump_local_portlist(char *msg, int mclag_id, int argc, char **argv);
|
||||
|
@ -101,12 +101,14 @@
|
||||
* ***************************************/
|
||||
static char *mlacp_state(struct CSM* csm);
|
||||
static void mlacp_resync_arp(struct CSM* csm);
|
||||
static void mlacp_resync_ndisc(struct CSM* csm);
|
||||
static void mlacp_resync_mac(struct CSM* csm);
|
||||
/* Sync Sender APIs*/
|
||||
static void mlacp_sync_send_sysConf(struct CSM* csm);
|
||||
static void mlacp_sync_send_aggConf(struct CSM* csm);
|
||||
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_heartbeat(struct CSM* csm);
|
||||
static void mlacp_sync_send_syncDoneData(struct CSM* csm);
|
||||
/* Sync Reciever APIs*/
|
||||
@ -204,7 +206,7 @@ static void mlacp_sync_send_aggState(struct CSM* csm)
|
||||
return;
|
||||
}
|
||||
#define MAX_MAC_ENTRY_NUM 30
|
||||
#define MAX_ARP_ENTRY_NUM 40
|
||||
#define MAX_NEIGH_ENTRY_NUM 40
|
||||
static void mlacp_sync_send_syncMacInfo(struct CSM* csm)
|
||||
{
|
||||
int msg_len = 0;
|
||||
@ -253,7 +255,7 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm)
|
||||
count++;
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
if (count >= MAX_ARP_ENTRY_NUM)
|
||||
if (count >= MAX_NEIGH_ENTRY_NUM)
|
||||
{
|
||||
iccp_csm_send(csm, g_csm_buf, msg_len);
|
||||
count = 0;
|
||||
@ -268,6 +270,37 @@ static void mlacp_sync_send_syncArpInfo(struct CSM* csm)
|
||||
return;
|
||||
}
|
||||
|
||||
static void mlacp_sync_send_syncNdiscInfo(struct CSM *csm)
|
||||
{
|
||||
int msg_len = 0;
|
||||
struct Msg *msg = NULL;
|
||||
int count = 0;
|
||||
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
|
||||
while (!TAILQ_EMPTY(&(MLACP(csm).ndisc_msg_list)))
|
||||
{
|
||||
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);
|
||||
count++;
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
if (count >= MAX_NEIGH_ENTRY_NUM)
|
||||
{
|
||||
iccp_csm_send(csm, g_csm_buf, msg_len);
|
||||
count = 0;
|
||||
memset(g_csm_buf, 0, CSM_BUFFER_SIZE);
|
||||
}
|
||||
/* ICCPD_LOG_DEBUG("mlacp_fsm", " [SYNC_Send] NDInfo,len=[%d]", msg_len); */
|
||||
}
|
||||
|
||||
if (count)
|
||||
iccp_csm_send(csm, g_csm_buf, msg_len);
|
||||
|
||||
return;
|
||||
}
|
||||
static void mlacp_sync_send_syncPortChannelInfo(struct CSM* csm)
|
||||
{
|
||||
struct System* sys = NULL;
|
||||
@ -353,7 +386,7 @@ 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_DEBUG(__FUNCTION__, "Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id);
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Same Node ID = %d, send NAK", MLACP(csm).remote_system.node_id);
|
||||
mlacp_sync_send_nak_handler(csm, msg);
|
||||
}
|
||||
|
||||
@ -476,6 +509,15 @@ static void mlacp_sync_recv_arpInfo(struct CSM* csm, struct Msg* msg)
|
||||
return;
|
||||
}
|
||||
|
||||
static void mlacp_sync_recv_ndiscInfo(struct CSM *csm, struct Msg *msg)
|
||||
{
|
||||
struct mLACPNDISCInfoTLV *ndisc_info = NULL;
|
||||
|
||||
ndisc_info = (struct mLACPNDISCInfoTLV *)&(msg->buf[sizeof(ICCHdr)]);
|
||||
mlacp_fsm_update_ndisc_info(csm, ndisc_info);
|
||||
|
||||
return;
|
||||
}
|
||||
static void mlacp_sync_recv_stpInfo(struct CSM* csm, struct Msg* msg)
|
||||
{
|
||||
/*Don't support currently*/
|
||||
@ -520,6 +562,7 @@ 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);
|
||||
PIF_QUEUE_REINIT(MLACP(csm).pif_list);
|
||||
LIF_PURGE_QUEUE_REINIT(MLACP(csm).lif_purge_list);
|
||||
@ -528,6 +571,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);
|
||||
LIF_QUEUE_REINIT(MLACP(csm).lif_list);
|
||||
|
||||
@ -551,8 +595,10 @@ void mlacp_finalize(struct CSM* csm)
|
||||
/* msg destroy*/
|
||||
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_MSG_QUEUE_REINIT(MLACP(csm).arp_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).ndisc_list);
|
||||
MLACP_MSG_QUEUE_REINIT(MLACP(csm).mac_list);
|
||||
|
||||
/* remove lif & lif-purge queue */
|
||||
@ -590,6 +636,7 @@ 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(csm).current_state = MLACP_STATE_INIT;
|
||||
}
|
||||
@ -651,6 +698,7 @@ void mlacp_fsm_transit(struct CSM* csm)
|
||||
MLACP(csm).wait_for_sync_data = 0;
|
||||
MLACP(csm).current_state = MLACP_STATE_STAGE1;
|
||||
mlacp_resync_arp(csm);
|
||||
mlacp_resync_ndisc(csm);
|
||||
}
|
||||
|
||||
switch (MLACP(csm).current_state)
|
||||
@ -788,7 +836,7 @@ static void mlacp_resync_arp(struct CSM* csm)
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).arp_list, tail)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
arp_msg->op_type = ARP_SYNC_ADD;
|
||||
arp_msg->op_type = NEIGH_SYNC_ADD;
|
||||
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);
|
||||
@ -797,6 +845,31 @@ static void mlacp_resync_arp(struct CSM* csm)
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* When peerlink ready, prepare the NDISCMsg
|
||||
*
|
||||
******************************************/
|
||||
static void mlacp_resync_ndisc(struct CSM *csm)
|
||||
{
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *ndisc_msg = NULL;
|
||||
struct Msg *msg_send = NULL;
|
||||
|
||||
/* recover ndisc info sync from peer */
|
||||
if (!TAILQ_EMPTY(&(MLACP(csm).ndisc_list)))
|
||||
{
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
ndisc_msg->op_type = NEIGH_SYNC_ADD;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* NAK handler
|
||||
*
|
||||
@ -928,6 +1001,10 @@ static void mlacp_sync_receiver_handler(struct CSM* csm, struct Msg* msg)
|
||||
mlacp_sync_recv_arpInfo(csm, msg);
|
||||
break;
|
||||
|
||||
case TLV_T_MLACP_NDISC_INFO:
|
||||
mlacp_sync_recv_ndiscInfo(csm, msg);
|
||||
break;
|
||||
|
||||
case TLV_T_MLACP_STP_INFO:
|
||||
mlacp_sync_recv_stpInfo(csm, msg);
|
||||
break;
|
||||
@ -980,6 +1057,10 @@ static void mlacp_sync_sender_handler(struct CSM* csm)
|
||||
mlacp_sync_send_syncArpInfo(csm);
|
||||
break;
|
||||
|
||||
case MLACP_SYNC_NDISC_INFO:
|
||||
mlacp_sync_send_syncNdiscInfo(csm);
|
||||
break;
|
||||
|
||||
case MLACP_SYNC_DONE:
|
||||
mlacp_sync_send_syncDoneData(csm);
|
||||
break;
|
||||
@ -1194,6 +1275,9 @@ static void mlacp_exchange_handler(struct CSM* csm, struct Msg* msg)
|
||||
/* Send ARP info if any*/
|
||||
mlacp_sync_send_syncArpInfo(csm);
|
||||
|
||||
/* Send Ndisc info if any */
|
||||
mlacp_sync_send_syncNdiscInfo(csm);
|
||||
|
||||
/*If peer is warm reboot*/
|
||||
if (csm->peer_warm_reboot_time != 0)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../include/iccp_csm.h"
|
||||
#include "mclagdctl/mclagdctl.h"
|
||||
#include "../include/iccp_cmd_show.h"
|
||||
#include "../include/iccp_netlink.h"
|
||||
/*****************************************
|
||||
* Enum
|
||||
*
|
||||
@ -50,12 +51,12 @@ typedef enum route_manipulate_type
|
||||
ROUTE_DEL
|
||||
} ROUTE_MANIPULATE_TYPE_E;
|
||||
|
||||
|
||||
/*****************************************
|
||||
* Global
|
||||
*
|
||||
* ***************************************/
|
||||
char g_ipv4_str[INET_ADDRSTRLEN];
|
||||
char g_ipv6_str[INET6_ADDRSTRLEN];
|
||||
|
||||
/*****************************************
|
||||
* Tool : show ip string
|
||||
@ -72,6 +73,14 @@ char *show_ip_str(uint32_t ipv4_addr)
|
||||
return g_ipv4_str;
|
||||
}
|
||||
|
||||
char *show_ipv6_str(char *ipv6_addr)
|
||||
{
|
||||
memset(g_ipv6_str, 0, sizeof(g_ipv6_str));
|
||||
inet_ntop(AF_INET6, ipv6_addr, g_ipv6_str, INET6_ADDRSTRLEN);
|
||||
|
||||
return g_ipv6_str;
|
||||
}
|
||||
|
||||
static int getHwAddr(char *buff, char *mac)
|
||||
{
|
||||
int i = 0;
|
||||
@ -95,107 +104,6 @@ static int getHwAddr(char *buff, char *mac)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set an entry in the ARP cache. */
|
||||
int mlacp_fsm_arp_set(char *ifname, uint32_t ip, char *mac)
|
||||
{
|
||||
struct arpreq arpreq;
|
||||
struct sockaddr_in *sin;
|
||||
struct in_addr ina;
|
||||
int flags;
|
||||
int rc;
|
||||
int sock_fd = 0;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Set arp entry for IP:%s MAC:%s ifname:%s", show_ip_str(htonl(ip)), mac, ifname);
|
||||
|
||||
if (ifname == NULL || ip == 0 || mac == NULL)
|
||||
{
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
/*you must add this becasue some system will return "Invlid argument"
|
||||
because some argument isn't zero */
|
||||
memset(&arpreq, 0, sizeof(struct arpreq));
|
||||
sin = (struct sockaddr_in *)&arpreq.arp_pa;
|
||||
memset(sin, 0, sizeof(struct sockaddr_in));
|
||||
sin->sin_family = AF_INET;
|
||||
ina.s_addr = htonl(ip);
|
||||
memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr));
|
||||
|
||||
if (getHwAddr((char *)arpreq.arp_ha.sa_data, mac) < 0)
|
||||
{
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
strncpy(arpreq.arp_dev, ifname, 15);
|
||||
|
||||
flags = ATF_COM; //note, must set flag, if not,you will get error
|
||||
|
||||
arpreq.arp_flags = flags;
|
||||
|
||||
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock_fd < 0)
|
||||
{
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
rc = ioctl(sock_fd, SIOCSARP, &arpreq);
|
||||
if (rc < 0)
|
||||
{
|
||||
close(sock_fd);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
close(sock_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Delete an entry from the ARP cache. */
|
||||
int mlacp_fsm_arp_del(char *ifname, uint32_t ip)
|
||||
{
|
||||
struct arpreq arpreq;
|
||||
struct sockaddr_in *sin;
|
||||
struct in_addr ina;
|
||||
int rc;
|
||||
int sock_fd = 0;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Del arp entry for IP : %s ifname:%s", show_ip_str(htonl(ip)), ifname);
|
||||
|
||||
if (ifname == NULL || ip == 0)
|
||||
{
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
/*you must add this becasue some system will return "Invlid argument"
|
||||
because some argument isn't zero */
|
||||
memset(&arpreq, 0, sizeof(struct arpreq));
|
||||
|
||||
sin = (struct sockaddr_in *)&arpreq.arp_pa;
|
||||
memset(sin, 0, sizeof(struct sockaddr_in));
|
||||
sin->sin_family = AF_INET;
|
||||
ina.s_addr = htonl(ip);
|
||||
memcpy(&sin->sin_addr, (char *)&ina, sizeof(struct in_addr));
|
||||
|
||||
strncpy(arpreq.arp_dev, ifname, 15);
|
||||
|
||||
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock_fd < 0)
|
||||
{
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
rc = ioctl(sock_fd, SIOCDARP, &arpreq);
|
||||
if (rc < 0)
|
||||
{
|
||||
close(sock_fd);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
close(sock_fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int arp_set_handler(struct CSM* csm,
|
||||
struct LocalInterface* lif,
|
||||
int add)
|
||||
@ -223,7 +131,7 @@ static int arp_set_handler(struct CSM* csm,
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
|
||||
/* only process add*/
|
||||
if (arp_msg->op_type == ARP_SYNC_DEL)
|
||||
if (arp_msg->op_type == NEIGH_SYNC_DEL)
|
||||
continue;
|
||||
|
||||
/* find the ARP for lif_list*/
|
||||
@ -233,9 +141,9 @@ static int arp_set_handler(struct CSM* csm,
|
||||
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_msg->mac_addr[0], arp_msg->mac_addr[1], arp_msg->mac_addr[2],
|
||||
arp_msg->mac_addr[3], arp_msg->mac_addr[4], arp_msg->mac_addr[5]);
|
||||
|
||||
mlacp_fsm_arp_set(arp_msg->ifname, arp_msg->ipv4_addr, mac_str);
|
||||
iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_msg->ipv4_addr, 1, arp_msg->mac_addr, arp_msg->ifname);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ARP to kernel [%s]",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
goto done;
|
||||
|
||||
@ -250,19 +158,82 @@ static int arp_set_handler(struct CSM* csm,
|
||||
continue;
|
||||
|
||||
/* don't process del*/
|
||||
if (arp_msg->op_type == ARP_SYNC_DEL)
|
||||
if (arp_msg->op_type == NEIGH_SYNC_DEL)
|
||||
continue;
|
||||
|
||||
/* link broken, del all dynamic arp on the lif*/
|
||||
mlacp_fsm_arp_del(arp_msg->ifname, arp_msg->ipv4_addr);
|
||||
iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_msg->ipv4_addr, 0, arp_msg->mac_addr, arp_msg->ifname);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ARP [%s]",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));*/
|
||||
show_ip_str(arp_msg->ipv4_addr));*/
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_set_handler(struct CSM *csm, struct LocalInterface *lif, int add)
|
||||
{
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *ndisc_msg = NULL;
|
||||
char mac_str[18] = "";
|
||||
|
||||
if (!csm || !lif)
|
||||
return 0;
|
||||
|
||||
if (add)
|
||||
goto add_ndisc;
|
||||
else
|
||||
goto del_ndisc;
|
||||
|
||||
/* Process Add */
|
||||
add_ndisc:
|
||||
if (MLACP(csm).current_state != MLACP_STATE_EXCHANGE)
|
||||
return 0;
|
||||
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
mac_str[0] = '\0';
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
/* only process add */
|
||||
if (ndisc_msg->op_type == NEIGH_SYNC_DEL)
|
||||
continue;
|
||||
|
||||
/* find the ND for lif_list */
|
||||
if (strcmp(lif->name, ndisc_msg->ifname) != 0)
|
||||
continue;
|
||||
|
||||
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", ndisc_msg->mac_addr[0], ndisc_msg->mac_addr[1], ndisc_msg->mac_addr[2],
|
||||
ndisc_msg->mac_addr[3], ndisc_msg->mac_addr[4], ndisc_msg->mac_addr[5]);
|
||||
|
||||
iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, 1, ndisc_msg->mac_addr, ndisc_msg->ifname);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Add dynamic ND to kernel [%s]", show_ipv6_str((char *)ndisc_msg->ipv6_addr));*/
|
||||
}
|
||||
goto done;
|
||||
|
||||
del_ndisc:
|
||||
/* Process Del */
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
/* find the ND for lif_list */
|
||||
if (strcmp(lif->name, ndisc_msg->ifname) != 0)
|
||||
continue;
|
||||
|
||||
/* don't process del */
|
||||
if (ndisc_msg->op_type == NEIGH_SYNC_DEL)
|
||||
continue;
|
||||
|
||||
/* link broken, del all dynamic ndisc on the lif */
|
||||
iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_msg->ipv6_addr, 0, ndisc_msg->mac_addr, ndisc_msg->ifname);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Del dynamic ND [%s]", show_ipv6_str((char *)ndisc_msg->ipv6_addr));*/
|
||||
}
|
||||
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Port-Channel Status Handler
|
||||
*
|
||||
@ -286,20 +257,13 @@ static void set_route_by_linux_route(struct CSM* csm,
|
||||
return;
|
||||
|
||||
sprintf(ipv4_dest_str, "%s", show_ip_str(htonl(local_if->ipv4_addr)));
|
||||
ptr = strrchr(ipv4_dest_str, '.'); strcpy(ptr, ".0\0");
|
||||
ptr = strrchr(ipv4_dest_str, '.');
|
||||
strcpy(ptr, ".0\0");
|
||||
|
||||
#if 1
|
||||
/* set gw route*/
|
||||
/*sprintf(syscmd, "ip route %s %s/%d proto static metric 200 nexthop via %s > /dev/null 2>&1",*/
|
||||
/* set gw route */
|
||||
/* sprintf(syscmd, "ip route %s %s/%d proto static metric 200 nexthop via %s > /dev/null 2>&1", */
|
||||
sprintf(syscmd, "ip route %s %s/%d metric 200 nexthop via %s > /dev/null 2>&1",
|
||||
(is_add) ? "add" : "del", ipv4_dest_str, local_if->prefixlen,
|
||||
csm->peer_ip);
|
||||
#else
|
||||
// set interface route
|
||||
sprintf(syscmd, "route %s -net %s/%d %s > /dev/null 2>&1",
|
||||
(is_add) ? "add" : "del", ipv4_dest_str, local_if->prefixlen,
|
||||
local_if->name);
|
||||
#endif
|
||||
(is_add) ? "add" : "del", ipv4_dest_str, local_if->prefixlen, csm->peer_ip);
|
||||
|
||||
ret = system(syscmd);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "%s ret = %d", syscmd, ret);
|
||||
@ -374,12 +338,14 @@ static void set_l3_itf_state(struct CSM *csm,
|
||||
if (strncmp(set_l3_local_if->name, VLAN_PREFIX, 4) != 0)
|
||||
{
|
||||
arp_set_handler(csm, set_l3_local_if, 0); /* del arp*/
|
||||
ndisc_set_handler(csm, set_l3_local_if, 0); /* del nd */
|
||||
}
|
||||
}
|
||||
else if (route_type == ROUTE_DEL)
|
||||
{
|
||||
/*set_route_by_linux_route(csm, set_l3_local_if, 0);*/ /*del static route by linux route tool*/
|
||||
arp_set_handler(csm, set_l3_local_if, 1); /* add arp*/
|
||||
ndisc_set_handler(csm, set_l3_local_if, 1); /* add nd */
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,7 +394,7 @@ static void mlacp_clean_fdb(void)
|
||||
if (sys->sync_fd)
|
||||
write(sys->sync_fd, msg_buf, msg_hdr->len);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Notify mclagsyncd to clear FDB");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Notify mclagsyncd to clear FDB");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -467,7 +433,7 @@ void set_peerlink_mlag_port_learn(struct LocalInterface *lif, int enable)
|
||||
msg_hdr->len += sizeof(mclag_sub_option_hdr_t);
|
||||
msg_hdr->len += sub_msg->op_len;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send %s port MAC learn msg to mclagsyncd for %s",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send %s port MAC learn msg to mclagsyncd for %s",
|
||||
sub_msg->op_type == MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE ? "DISABLE":"ENABLE", lif->name);
|
||||
|
||||
/*send msg*/
|
||||
@ -489,12 +455,12 @@ static void set_peerlink_mlag_port_kernel_forward(
|
||||
|
||||
sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP",
|
||||
"-D", csm->peer_link_if->name, lif->name);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s", cmd );
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, " ebtable cmd %s", cmd );
|
||||
system(cmd);
|
||||
|
||||
sprintf(cmd, "ebtables %s FORWARD -i %s -o %s -j DROP",
|
||||
(enable) ? "-A" : "-D", csm->peer_link_if->name, lif->name);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, " ebtable cmd %s", cmd );
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, " ebtable cmd %s", cmd );
|
||||
system(cmd);
|
||||
|
||||
return;
|
||||
@ -600,11 +566,11 @@ void update_peerlink_isolate_from_all_csm_lif(
|
||||
if (dst_len)
|
||||
{
|
||||
memcpy(sub_msg->data, mlag_po_buf, dst_len);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port %s", csm->peer_link_if->name, mlag_po_buf);
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port %s", csm->peer_link_if->name, mlag_po_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port is NULL", csm->peer_link_if->name);
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send port isolate msg to mclagsyncd, src port %s, dst port is NULL", csm->peer_link_if->name);
|
||||
}
|
||||
|
||||
/*send msg*/
|
||||
@ -902,7 +868,7 @@ void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if)
|
||||
continue;
|
||||
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
arp_msg->op_type = ARP_SYNC_ADD;
|
||||
arp_msg->op_type = NEIGH_SYNC_ADD;
|
||||
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)arp_msg, sizeof(struct ARPMsg)) == 0)
|
||||
{
|
||||
@ -912,13 +878,46 @@ void syn_arp_info_to_peer(struct CSM *csm, struct LocalInterface *local_if)
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ARP[ADD] for %s",
|
||||
show_ip_str(htonl(arp_msg->ipv4_addr)));
|
||||
show_ip_str(arp_msg->ipv4_addr));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void syn_ndisc_info_to_peer(struct CSM *csm, struct LocalInterface *local_if)
|
||||
{
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *ndisc_msg = NULL, *ndisc_info = NULL;
|
||||
struct Msg *msg_send = NULL;
|
||||
|
||||
if (!csm || !local_if)
|
||||
return;
|
||||
|
||||
if (!TAILQ_EMPTY(&(MLACP(csm).ndisc_list)))
|
||||
{
|
||||
TAILQ_FOREACH(msg, &MLACP(csm).ndisc_list, tail)
|
||||
{
|
||||
ndisc_info = (struct NDISCMsg *)msg->buf;
|
||||
|
||||
if (strcmp(ndisc_info->ifname, local_if->name) != 0)
|
||||
continue;
|
||||
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
ndisc_msg->op_type = NEIGH_SYNC_ADD;
|
||||
|
||||
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);
|
||||
/*ICCPD_LOG_DEBUG(__FUNCTION__, "Enqueue ND[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));*/
|
||||
}
|
||||
else
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to enqueue ND[ADD] for %s", show_ipv6_str((char *)ndisc_msg->ipv6_addr));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
void update_stp_peer_link(struct CSM *csm,
|
||||
struct PeerInterface *pif,
|
||||
int po_state, int new_create)
|
||||
@ -948,6 +947,7 @@ void update_stp_peer_link(struct CSM *csm,
|
||||
if (po_state == 1 && lif->po_active == 1)
|
||||
{
|
||||
syn_arp_info_to_peer(csm, lif);
|
||||
syn_ndisc_info_to_peer(csm, lif);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -972,6 +972,7 @@ void update_stp_peer_link(struct CSM *csm,
|
||||
if (po_state == 1 && lif->po_active == 1)
|
||||
{
|
||||
syn_arp_info_to_peer(csm, vlan->vlan_itf);
|
||||
syn_ndisc_info_to_peer(csm, vlan->vlan_itf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1034,7 +1035,7 @@ void iccp_send_fdb_entry_to_syncd( struct MACMsg* mac_msg, uint8_t mac_type)
|
||||
mac_info->op_type = mac_msg->op_type;
|
||||
msg_hdr->len = sizeof(struct IccpSyncdHDr) + sizeof(struct mclag_fdb_info);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send mac %s msg to mclagsyncd, vid %d ; ifname %s ; mac %s; type %s",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send mac %s msg to mclagsyncd, vid %d ; ifname %s ; mac %s; type %s",
|
||||
mac_info->op_type == MAC_SYNC_ADD ? "add" : "del", mac_info->vid, mac_info->port_name, mac_info->mac, mac_info->type == MAC_TYPE_STATIC ? "static" : "dynamic");
|
||||
|
||||
/*send msg*/
|
||||
@ -1141,7 +1142,7 @@ static void update_l2_mac_state(struct CSM *csm,
|
||||
/*portchannel down*/
|
||||
if (po_state == 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, age local MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s down, age local MAC %s vlan-id %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
|
||||
mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1);
|
||||
@ -1180,7 +1181,7 @@ static void update_l2_mac_state(struct CSM *csm,
|
||||
memcpy(mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ);
|
||||
}
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, redirect MAC %s vlan-id %d to peer-link %s",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s down, redirect MAC %s vlan-id %d to peer-link %s",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, csm->peer_itf_name);
|
||||
}
|
||||
else
|
||||
@ -1188,7 +1189,7 @@ static void update_l2_mac_state(struct CSM *csm,
|
||||
/*peer-link is not configured, del mac from ASIC, mac still in mac_list*/
|
||||
del_mac_from_chip(mac_msg);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s down, peer-link is not configured: MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s down, peer-link is not configured: MAC %s vlan-id %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
}
|
||||
}
|
||||
@ -1199,7 +1200,7 @@ static void update_l2_mac_state(struct CSM *csm,
|
||||
/*when this portchannel up, recover the mac back*/
|
||||
if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s up, redirect MAC %s vlan-id %d from peerlink to %s",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s up, redirect MAC %s vlan-id %d from peerlink to %s",
|
||||
mac_msg->origin_ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->origin_ifname);
|
||||
|
||||
/*Remove MAC_AGE_LOCAL flag*/
|
||||
@ -1215,7 +1216,7 @@ static void update_l2_mac_state(struct CSM *csm,
|
||||
{
|
||||
/*this may be peerlink is not configured and portchannel is down*/
|
||||
/*when this portchannel up, add the mac back to ASIC*/
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Intf %s up, add MAC %s vlan-id %d to ASIC",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Intf %s up, add MAC %s vlan-id %d to ASIC",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
|
||||
/*Remove MAC_AGE_LOCAL flag*/
|
||||
@ -1319,7 +1320,7 @@ static void mlacp_fix_bridge_mac(struct CSM* csm)
|
||||
/*The Bridge mac can not be the same as peer system id, so fix the Bridge MAC address here.*/
|
||||
sprintf(syscmd, "ip link set dev Bridge address %s > /dev/null 2>&1", macaddr);
|
||||
ret = system(syscmd);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, " %s ret = %d", syscmd, ret);
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, " %s ret = %d", syscmd, ret);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -1345,7 +1346,7 @@ void mlacp_peer_conn_handler(struct CSM* csm)
|
||||
{
|
||||
/*If peer reconnected, reset peer disconnect time*/
|
||||
csm->warm_reboot_disconn_time = 0;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot and reconnect, reset peer disconnect time!");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot and reconnect, reset peer disconnect time!");
|
||||
}
|
||||
|
||||
if (csm->peer_link_if)
|
||||
@ -1368,36 +1369,10 @@ void mlacp_peer_conn_handler(struct CSM* csm)
|
||||
|
||||
mlacp_conn_handler_fdb(csm);
|
||||
|
||||
#if 0
|
||||
// When peer-link ready, suppose all MLAG link are alive
|
||||
LIST_FOREACH(pif, &(MLACP(csm).pif_list), mlacp_next)
|
||||
{
|
||||
pif->po_active = 1;
|
||||
}
|
||||
#endif
|
||||
LIST_FOREACH(lif, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
if (lif->type == IF_T_PORT_CHANNEL)
|
||||
{
|
||||
#if 0
|
||||
if (local_if_is_l3_mode(lif))
|
||||
{
|
||||
set_route_by_linux_route( csm, lif, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
LIST_FOREACH(vlan, &(lif->vlan_list), port_next)
|
||||
{
|
||||
if (!vlan->vlan_itf)
|
||||
continue;
|
||||
if (!local_if_is_l3_mode(vlan->vlan_itf))
|
||||
continue;
|
||||
|
||||
set_route_by_linux_route(csm, vlan->vlan_itf, 1); /* add static route by linux route tool*/
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mlacp_portchannel_state_handler(csm, lif, (lif->state == PORT_STATE_UP) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
@ -1432,7 +1407,7 @@ void mlacp_peer_disconn_handler(struct CSM* csm)
|
||||
/*peer connection must be establised again within 90s
|
||||
from last disconnection for peer warm reboot*/
|
||||
time(&csm->warm_reboot_disconn_time);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peer warm reboot and disconnect, recover to normal reboot for next time!");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peer warm reboot and disconnect, recover to normal reboot for next time!");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1448,7 +1423,7 @@ void mlacp_peer_disconn_handler(struct CSM* csm)
|
||||
if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0 && mac_msg->age_flag != (MAC_AGE_LOCAL | MAC_AGE_PEER))
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peer disconnect, del MAC for peer-link: %s, MAC %s vlan-id %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
|
||||
/*Send mac del message to mclagsyncd, may be already deleted*/
|
||||
@ -1493,7 +1468,7 @@ void mlacp_peerlink_up_handler(struct CSM* csm)
|
||||
if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link up, add MAC to ASIC for peer-link: %s, MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peer link up, add MAC to ASIC for peer-link: %s, MAC %s vlan-id %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
|
||||
/*Send mac add message to mclagsyncd, local age flag is already set*/
|
||||
@ -1520,7 +1495,7 @@ void mlacp_peerlink_down_handler(struct CSM* csm)
|
||||
if (strcmp(mac_msg->ifname, csm->peer_itf_name) != 0)
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peer link down, del MAC for peer-link: %s, MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peer link down, del MAC for peer-link: %s, MAC %s vlan-id %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
|
||||
mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1);
|
||||
@ -1686,17 +1661,7 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch
|
||||
|
||||
mac_msg->age_flag = 0;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC msg from mclagsyncd, vid %d mac %s port %s optype %s ", vid, mac_str, ifname, op_type == MAC_SYNC_ADD ? "add" : "del");
|
||||
/*Debug*/
|
||||
#if 0
|
||||
/* dump receive MAC info*/
|
||||
fprintf(stderr, "\n======== MAC Update==========\n");
|
||||
fprintf(stderr, " MAC = %s\n", mac_str);
|
||||
fprintf(stderr, " vlan id = %d\n", vid);
|
||||
fprintf(stderr, " fdb type = %s\n", fdb_type == MAC_TYPE_STATIC ? "static" : "dynamic");
|
||||
fprintf(stderr, " op type = %s\n", op_type == MAC_SYNC_ADD ? "add" : "del");
|
||||
fprintf(stderr, "==============================\n");
|
||||
#endif
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC msg from mclagsyncd, vid %d mac %s port %s optype %s ", vid, mac_str, ifname, op_type == MAC_SYNC_ADD ? "add" : "del");
|
||||
|
||||
/* Find MLACP itf, may be mclag enabled port-channel*/
|
||||
LIST_FOREACH(csm, &(sys->csm_list), next)
|
||||
@ -1868,7 +1833,7 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch
|
||||
/*peer-link learn mac is control by iccpd, ignore the chip del info*/
|
||||
add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(peer-link is up), add back %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC del msg: %s(peer-link is up), add back %s vlan-id %d",
|
||||
mac_info->ifname, mac_info->mac_str, mac_info->vid);
|
||||
}
|
||||
|
||||
@ -1890,7 +1855,7 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age, add back to chip",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC del msg: %s, del %s vlan-id %d, peer is not age, add back to chip",
|
||||
mac_info->ifname, mac_info->mac_str, mac_info->vid);
|
||||
|
||||
mac_info->fdb_type = MAC_TYPE_DYNAMIC;
|
||||
@ -1905,7 +1870,7 @@ void do_mac_update_from_syncd(char mac_str[ETHER_ADDR_STR_LEN], uint16_t vid, ch
|
||||
if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP)
|
||||
{
|
||||
add_mac_to_chip(mac_info, MAC_TYPE_DYNAMIC);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Recv MAC del msg: %s(down), del %s vlan-id %d, redirect to peer-link",
|
||||
mac_info->ifname, mac_info->mac_str, mac_info->vid);
|
||||
}
|
||||
}
|
||||
@ -1984,6 +1949,9 @@ char * mclagd_ctl_cmd_str(int req_type)
|
||||
case INFO_TYPE_DUMP_ARP:
|
||||
return "dump arp";
|
||||
|
||||
case INFO_TYPE_DUMP_NDISC:
|
||||
return "dump nd";
|
||||
|
||||
case INFO_TYPE_DUMP_MAC:
|
||||
return "dump mac";
|
||||
|
||||
@ -2205,6 +2173,46 @@ void mclagd_ctl_handle_dump_arp(int client_fd, int mclag_id)
|
||||
return;
|
||||
}
|
||||
|
||||
void mclagd_ctl_handle_dump_ndisc(int client_fd, int mclag_id)
|
||||
{
|
||||
char *Pbuf = NULL;
|
||||
char buf[512] = { 0 };
|
||||
int ndisc_num = 0;
|
||||
int ret = 0;
|
||||
struct mclagd_reply_hdr *hd = NULL;
|
||||
int len_tmp = 0;
|
||||
|
||||
ret = iccp_ndisc_dump(&Pbuf, &ndisc_num, mclag_id);
|
||||
if (ret != EXEC_TYPE_SUCCESS)
|
||||
{
|
||||
len_tmp = sizeof(struct mclagd_reply_hdr);
|
||||
memcpy(buf, &len_tmp, sizeof(int));
|
||||
hd = (struct mclagd_reply_hdr *)(buf + sizeof(int));
|
||||
hd->exec_result = ret;
|
||||
hd->info_type = INFO_TYPE_DUMP_NDISC;
|
||||
hd->data_len = 0;
|
||||
mclagd_ctl_sock_write(client_fd, buf, MCLAGD_REPLY_INFO_HDR);
|
||||
|
||||
if (Pbuf)
|
||||
free(Pbuf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
hd = (struct mclagd_reply_hdr *)(Pbuf + sizeof(int));
|
||||
hd->exec_result = EXEC_TYPE_SUCCESS;
|
||||
hd->info_type = INFO_TYPE_DUMP_NDISC;
|
||||
hd->data_len = ndisc_num * sizeof(struct mclagd_ndisc_msg);
|
||||
len_tmp = (hd->data_len + sizeof(struct mclagd_reply_hdr));
|
||||
memcpy(Pbuf, &len_tmp, sizeof(int));
|
||||
mclagd_ctl_sock_write(client_fd, Pbuf, MCLAGD_REPLY_INFO_HDR + hd->data_len);
|
||||
|
||||
if (Pbuf)
|
||||
free(Pbuf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mclagd_ctl_handle_dump_mac(int client_fd, int mclag_id)
|
||||
{
|
||||
char * Pbuf = NULL;
|
||||
@ -2375,6 +2383,10 @@ int mclagd_ctl_interactive_process(int client_fd)
|
||||
mclagd_ctl_handle_dump_arp(client_fd, req->mclag_id);
|
||||
break;
|
||||
|
||||
case INFO_TYPE_DUMP_NDISC:
|
||||
mclagd_ctl_handle_dump_ndisc(client_fd, req->mclag_id);
|
||||
break;
|
||||
|
||||
case INFO_TYPE_DUMP_MAC:
|
||||
mclagd_ctl_handle_dump_mac(client_fd, req->mclag_id);
|
||||
break;
|
||||
|
@ -326,7 +326,7 @@ int mlacp_prepare_for_mac_info_to_peer(struct CSM* csm, char* buf, size_t max_bu
|
||||
sprintf(MacData->ifname, "%s", mac_msg->origin_ifname);
|
||||
MacData->vid = htons(mac_msg->vid);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Send MAC messge to peer, port %s mac = %s, vid = %d, type = %s count %d ", mac_msg->origin_ifname,
|
||||
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);
|
||||
|
||||
return msg_len;
|
||||
@ -374,11 +374,64 @@ int mlacp_prepare_for_arp_info(struct CSM* csm, char* buf, size_t max_buf_size,
|
||||
|
||||
ArpData->op_type = arp_msg->op_type;
|
||||
sprintf(ArpData->ifname, "%s", arp_msg->ifname);
|
||||
ArpData->ipv4_addr = htonl(arp_msg->ipv4_addr);
|
||||
ArpData->ipv4_addr = arp_msg->ipv4_addr;
|
||||
memcpy(ArpData->mac_addr, arp_msg->mac_addr, ETHER_ADDR_LEN);
|
||||
|
||||
ICCPD_LOG_DEBUG(__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_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));
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* 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)
|
||||
{
|
||||
|
||||
struct mLACPNDISCInfoTLV *tlv = NULL;
|
||||
size_t msg_len = 0;
|
||||
size_t tlv_len = 0;
|
||||
ICCHdr *icc_hdr = NULL;
|
||||
struct NDISCMsg *NdiscData;
|
||||
|
||||
if (!csm)
|
||||
return -1;
|
||||
if (!buf)
|
||||
return -1;
|
||||
|
||||
tlv_len = sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * (count + 1);
|
||||
|
||||
if ((msg_len = sizeof(ICCHdr) + tlv_len) > max_buf_size)
|
||||
return -1;
|
||||
|
||||
/* ICC header */
|
||||
icc_hdr = (ICCHdr *)buf;
|
||||
mlacp_fill_icc_header(csm, icc_hdr, msg_len);
|
||||
|
||||
/* Prepare for ND information TLV */
|
||||
tlv = (struct mLACPNDISCInfoTLV *)&buf[sizeof(ICCHdr)];
|
||||
tlv->icc_parameter.len = htons(tlv_len - sizeof(ICCParameter));
|
||||
tlv->num_of_entry = htons(count + 1);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
tlv->icc_parameter.u_bit = 0;
|
||||
tlv->icc_parameter.f_bit = 0;
|
||||
tlv->icc_parameter.type = htons(TLV_T_MLACP_NDISC_INFO);
|
||||
}
|
||||
|
||||
NdiscData = (struct mLACPMACData *)&buf[sizeof(ICCHdr) + sizeof(struct mLACPNDISCInfoTLV) + sizeof(struct NDISCMsg) * count];
|
||||
|
||||
NdiscData->op_type = ndisc_msg->op_type;
|
||||
sprintf(NdiscData->ifname, "%s", ndisc_msg->ifname);
|
||||
memcpy(NdiscData->ipv6_addr, ndisc_msg->ipv6_addr, 32);
|
||||
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,
|
||||
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));
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
@ -597,7 +650,7 @@ 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(__FUNCTION__, "Send warm reboot notification to peer!");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Send warm reboot notification to peer!");
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "../include/mlacp_link_handler.h"
|
||||
#include "../include/iccp_consistency_check.h"
|
||||
#include "../include/port.h"
|
||||
#include "../include/iccp_netlink.h"
|
||||
/*****************************************
|
||||
* Port-Conf Update
|
||||
*
|
||||
@ -166,7 +167,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *
|
||||
struct LocalInterface* local_if = NULL;
|
||||
uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/
|
||||
|
||||
ICCPD_LOG_INFO(__FUNCTION__,
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__,
|
||||
"Received MAC Info, port[%s] vid[%d] MAC[%s] type[%s]",
|
||||
MacData->ifname, ntohs(MacData->vid), MacData->mac_str, MacData->type == MAC_SYNC_ADD ? "add" : "del");
|
||||
|
||||
@ -266,27 +267,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *
|
||||
add_mac_to_chip(mac_msg, MAC_TYPE_DYNAMIC);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
mac_msg->op_type = MAC_SYNC_ACK;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0)
|
||||
{
|
||||
/*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), msg_send, tail);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ADD, MAC-msg-list enqueue: %s, add %s vlan-id %d, op_type %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
else if (tlv->type == MAC_SYNC_ACK)
|
||||
{
|
||||
/*Clean the MAC_AGE_PEER flag*/
|
||||
mac_msg->age_flag &= ~MAC_AGE_PEER;
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Recv ACK, Remove peer age flag:%d ifname %s, add %s vlan-id %d, op_type %d",
|
||||
mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
@ -332,7 +313,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *
|
||||
|
||||
if (strlen(csm->peer_itf_name) == 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "From orphan port or portchannel is down, but peer-link is not configured: ifname %s, MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "From orphan port or portchannel is down, but peer-link is not configured: ifname %s, MAC %s vlan-id %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
|
||||
/*if orphan port mac but no peerlink, don't keep this mac*/
|
||||
@ -344,7 +325,7 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *
|
||||
/*Redirect the mac to peer-link*/
|
||||
memcpy(&mac_msg->ifname, csm->peer_itf_name, IFNAMSIZ);
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, MAC %s vlan-id %d",
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Redirect to peerlink for orphan port or portchannel is down, Add local age flag: %d ifname %s, MAC %s vlan-id %d",
|
||||
mac_msg->age_flag, mac_msg->ifname, mac_msg->mac_str, mac_msg->vid);
|
||||
}
|
||||
}
|
||||
@ -371,17 +352,6 @@ int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *
|
||||
/*from MCLAG port and the local port is up*/
|
||||
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
|
||||
}
|
||||
|
||||
#if 0
|
||||
mac_msg->op_type = MAC_SYNC_ACK;
|
||||
if (iccp_csm_init_msg(&msg_send, (char*)mac_msg, sizeof(struct MACMsg)) == 0)
|
||||
{
|
||||
/*Reply mac ack message to peer, peer will clean MAC_AGE_PEER flag*/
|
||||
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, op_type %d",
|
||||
mac_msg->ifname, mac_msg->mac_str, mac_msg->vid, mac_msg->op_type);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,7 +392,7 @@ void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg)
|
||||
return;
|
||||
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
if (arp_msg->op_type != ARP_SYNC_DEL)
|
||||
if (arp_msg->op_type != NEIGH_SYNC_DEL)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).arp_list), msg, tail);
|
||||
}
|
||||
@ -430,6 +400,32 @@ void mlacp_enqueue_arp(struct CSM* csm, struct Msg* msg)
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Tool : Add Ndisc Info into ndisc list
|
||||
*
|
||||
****************************************/
|
||||
void mlacp_enqueue_ndisc(struct CSM *csm, struct Msg *msg)
|
||||
{
|
||||
struct NDISCMsg *ndisc_msg = NULL;
|
||||
|
||||
if (!csm)
|
||||
{
|
||||
if (msg)
|
||||
free(msg);
|
||||
return;
|
||||
}
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
if (ndisc_msg->op_type != NEIGH_SYNC_DEL)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&(MLACP(csm).ndisc_list), msg, tail);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* ARP-Info Update
|
||||
* ***************************************/
|
||||
@ -449,7 +445,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2],
|
||||
arp_entry->mac_addr[3], arp_entry->mac_addr[4], arp_entry->mac_addr[5]);
|
||||
|
||||
ICCPD_LOG_INFO(__FUNCTION__,
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__,
|
||||
"Received ARP Info, intf[%s] IP[%s], MAC[%02x:%02x:%02x:%02x:%02x:%02x]",
|
||||
arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr),
|
||||
arp_entry->mac_addr[0], arp_entry->mac_addr[1], arp_entry->mac_addr[2],
|
||||
@ -537,9 +533,9 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
/* set dynamic ARP*/
|
||||
if (set_arp_flag == 1)
|
||||
{
|
||||
if (arp_entry->op_type == ARP_SYNC_ADD)
|
||||
if (arp_entry->op_type == NEIGH_SYNC_ADD)
|
||||
{
|
||||
if (mlacp_fsm_arp_set(arp_entry->ifname, ntohl(arp_entry->ipv4_addr), mac_str) < 0)
|
||||
if (iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_entry->ipv4_addr, 1, arp_entry->mac_addr, arp_entry->ifname) < 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "ARP add failure for %s %s %s",
|
||||
arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str);
|
||||
@ -548,7 +544,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mlacp_fsm_arp_del(arp_entry->ifname, ntohl(arp_entry->ipv4_addr)) < 0)
|
||||
if (iccp_netlink_neighbor_request(AF_INET, (uint8_t *)&arp_entry->ipv4_addr, 0, arp_entry->mac_addr, arp_entry->ifname) < 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "ARP delete failure for %s %s %s",
|
||||
arp_entry->ifname, show_ip_str(arp_entry->ipv4_addr), mac_str);
|
||||
@ -561,7 +557,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Failure: port-channel is not alive");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Failure: port-channel is not alive");
|
||||
/*TODO Set static route through peer-link or just skip it?*/
|
||||
}
|
||||
|
||||
@ -569,7 +565,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
TAILQ_FOREACH(msg, &(MLACP(csm).arp_list), tail)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
if (arp_msg->ipv4_addr == ntohl(arp_entry->ipv4_addr))
|
||||
if (arp_msg->ipv4_addr == arp_entry->ipv4_addr)
|
||||
{
|
||||
/*arp_msg->op_type = tlv->type;*/
|
||||
sprintf(arp_msg->ifname, "%s", arp_entry->ifname);
|
||||
@ -579,18 +575,18 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
}
|
||||
|
||||
/* delete/add ARP list*/
|
||||
if (msg && arp_entry->op_type == ARP_SYNC_DEL)
|
||||
if (msg && arp_entry->op_type == NEIGH_SYNC_DEL)
|
||||
{
|
||||
TAILQ_REMOVE(&(MLACP(csm).arp_list), msg, tail);
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
/*ICCPD_LOG_INFO(__FUNCTION__, "Del arp queue successfully");*/
|
||||
}
|
||||
else if (!msg && arp_entry->op_type == ARP_SYNC_ADD)
|
||||
else if (!msg && arp_entry->op_type == NEIGH_SYNC_ADD)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)&arp_data;
|
||||
sprintf(arp_msg->ifname, "%s", arp_entry->ifname);
|
||||
arp_msg->ipv4_addr = ntohl(arp_entry->ipv4_addr);
|
||||
arp_msg->ipv4_addr = arp_entry->ipv4_addr;
|
||||
arp_msg->op_type = arp_entry->op_type;
|
||||
memcpy(arp_msg->mac_addr, arp_entry->mac_addr, ETHER_ADDR_LEN);
|
||||
if (iccp_csm_init_msg(&msg, (char*)arp_msg, sizeof(struct ARPMsg)) == 0)
|
||||
@ -604,7 +600,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
if (arp_msg->ipv4_addr == ntohl(arp_entry->ipv4_addr))
|
||||
if (arp_msg->ipv4_addr == arp_entry->ipv4_addr)
|
||||
break;
|
||||
}
|
||||
|
||||
@ -617,7 +613,7 @@ int mlacp_fsm_update_arp_entry(struct CSM* csm, struct ARPMsg *arp_entry)
|
||||
TAILQ_FOREACH(msg, &(MLACP(csm).arp_msg_list), tail)
|
||||
{
|
||||
arp_msg = (struct ARPMsg*)msg->buf;
|
||||
if (arp_msg->ipv4_addr == ntohl(arp_entry->ipv4_addr))
|
||||
if (arp_msg->ipv4_addr == arp_entry->ipv4_addr)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -641,6 +637,216 @@ int mlacp_fsm_update_arp_info(struct CSM* csm, struct mLACPARPInfoTLV* tlv)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* NDISC-Info Update
|
||||
* ***************************************/
|
||||
int mlacp_fsm_update_ndisc_entry(struct CSM *csm, struct NDISCMsg *ndisc_entry)
|
||||
{
|
||||
struct Msg *msg = NULL;
|
||||
struct NDISCMsg *ndisc_msg = NULL, ndisc_data;
|
||||
struct LocalInterface *local_if;
|
||||
struct LocalInterface *peer_link_if = NULL;
|
||||
struct VLAN_ID *vlan_id_list = NULL;
|
||||
int set_ndisc_flag = 0;
|
||||
char mac_str[18] = "";
|
||||
|
||||
if (!csm || !ndisc_entry)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
sprintf(mac_str, "%02x:%02x:%02x:%02x:%02x:%02x", ndisc_entry->mac_addr[0], ndisc_entry->mac_addr[1], ndisc_entry->mac_addr[2],
|
||||
ndisc_entry->mac_addr[3], ndisc_entry->mac_addr[4], ndisc_entry->mac_addr[5]);
|
||||
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__,
|
||||
"Received ND Info, intf[%s] IP[%s], MAC[%s]", ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str);
|
||||
|
||||
if (strncmp(ndisc_entry->ifname, "Vlan", 4) == 0)
|
||||
{
|
||||
peer_link_if = local_if_find_by_name(csm->peer_itf_name);
|
||||
|
||||
if (peer_link_if && !local_if_is_l3_mode(peer_link_if))
|
||||
{
|
||||
/* Is peer-linlk itf belong to a vlan the same as peer? */
|
||||
LIST_FOREACH(vlan_id_list, &(peer_link_if->vlan_list), port_next)
|
||||
{
|
||||
if (!vlan_id_list->vlan_itf)
|
||||
continue;
|
||||
if (strcmp(vlan_id_list->vlan_itf->name, ndisc_entry->ifname) != 0)
|
||||
continue;
|
||||
if (!local_if_is_l3_mode(vlan_id_list->vlan_itf))
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__,
|
||||
"ND is learnt from intf %s, peer-link %s is the member of this vlan",
|
||||
vlan_id_list->vlan_itf->name, peer_link_if->name);
|
||||
|
||||
/* Peer-link belong to L3 vlan is alive, set the NDISC info */
|
||||
set_ndisc_flag = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set_ndisc_flag == 0)
|
||||
{
|
||||
LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next)
|
||||
{
|
||||
if (local_if->type == IF_T_PORT_CHANNEL)
|
||||
{
|
||||
if (!local_if_is_l3_mode(local_if))
|
||||
{
|
||||
/* Is the L2 MLAG itf belong to a vlan the same as peer? */
|
||||
LIST_FOREACH(vlan_id_list, &(local_if->vlan_list), port_next)
|
||||
{
|
||||
if (!vlan_id_list->vlan_itf)
|
||||
continue;
|
||||
if (strcmp(vlan_id_list->vlan_itf->name, ndisc_entry->ifname) != 0)
|
||||
continue;
|
||||
if (!local_if_is_l3_mode(vlan_id_list->vlan_itf))
|
||||
continue;
|
||||
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__,
|
||||
"ND is learnt from intf %s, %s is the member of this vlan", vlan_id_list->vlan_itf->name, local_if->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (vlan_id_list && local_if->po_active == 1)
|
||||
{
|
||||
/* Any po of L3 vlan is alive, set the NDISC info */
|
||||
set_ndisc_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Is the ARP belong to a L3 mode MLAG itf? */
|
||||
if (strcmp(local_if->name, ndisc_entry->ifname) == 0)
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "ND is learnt from mclag L3 intf %s", local_if->name);
|
||||
if (local_if->po_active == 1)
|
||||
{
|
||||
/* po is alive, set the NDISC info */
|
||||
set_ndisc_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set dynamic Ndisc */
|
||||
if (set_ndisc_flag == 1)
|
||||
{
|
||||
if (ndisc_entry->op_type == NEIGH_SYNC_ADD)
|
||||
{
|
||||
if (iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_entry->ipv6_addr, 1, ndisc_entry->mac_addr, ndisc_entry->ifname) < 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to add nd entry(%s %s %s) to kernel",
|
||||
ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iccp_netlink_neighbor_request(AF_INET6, (uint8_t *)ndisc_entry->ipv6_addr, 0, ndisc_entry->mac_addr, ndisc_entry->ifname) < 0)
|
||||
{
|
||||
ICCPD_LOG_WARN(__FUNCTION__, "Failed to delete nd entry(%s %s %s) from kernel",
|
||||
ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str);
|
||||
return MCLAG_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ICCPD_LOG_DEBUG(__FUNCTION__, "NDISC update for %s %s %s", ndisc_entry->ifname, show_ipv6_str((char *)ndisc_entry->ipv6_addr), mac_str); */
|
||||
}
|
||||
else
|
||||
{
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Failure: port-channel is not alive");
|
||||
/* TODO Set static route through peer-link or just skip it? */
|
||||
}
|
||||
|
||||
/* update NDISC list */
|
||||
TAILQ_FOREACH(msg, &(MLACP(csm).ndisc_list), tail)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
if (memcmp((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16) == 0)
|
||||
{
|
||||
/* ndisc_msg->op_type = tlv->type; */
|
||||
sprintf(ndisc_msg->ifname, "%s", ndisc_entry->ifname);
|
||||
memcpy(ndisc_msg->mac_addr, ndisc_entry->mac_addr, ETHER_ADDR_LEN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* delete/add NDISC list */
|
||||
if (msg && ndisc_entry->op_type == NEIGH_SYNC_DEL)
|
||||
{
|
||||
TAILQ_REMOVE(&(MLACP(csm).ndisc_list), msg, tail);
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
/* ICCPD_LOG_INFO(__FUNCTION__, "Del ndisc queue successfully"); */
|
||||
}
|
||||
else if (!msg && ndisc_entry->op_type == NEIGH_SYNC_ADD)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)&ndisc_data;
|
||||
sprintf(ndisc_msg->ifname, "%s", ndisc_entry->ifname);
|
||||
memcpy((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16);
|
||||
ndisc_msg->op_type = ndisc_entry->op_type;
|
||||
memcpy(ndisc_msg->mac_addr, ndisc_entry->mac_addr, ETHER_ADDR_LEN);
|
||||
if (iccp_csm_init_msg(&msg, (char *)ndisc_msg, sizeof(struct NDISCMsg)) == 0)
|
||||
{
|
||||
mlacp_enqueue_ndisc(csm, msg);
|
||||
/* ICCPD_LOG_INFO(__FUNCTION__, "Add ndisc queue successfully"); */
|
||||
}
|
||||
}
|
||||
|
||||
/* remove all NDISC msg queue, when receive peer's NDISC list at the same time */
|
||||
TAILQ_FOREACH(msg, &(MLACP(csm).ndisc_msg_list), tail)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
if (memcmp((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
while (msg)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
TAILQ_REMOVE(&(MLACP(csm).ndisc_msg_list), msg, tail);
|
||||
free(msg->buf);
|
||||
free(msg);
|
||||
TAILQ_FOREACH(msg, &(MLACP(csm).ndisc_msg_list), tail)
|
||||
{
|
||||
ndisc_msg = (struct NDISCMsg *)msg->buf;
|
||||
if (memcmp((char *)ndisc_msg->ipv6_addr, (char *)ndisc_entry->ipv6_addr, 16) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mlacp_fsm_update_ndisc_info(struct CSM *csm, struct mLACPNDISCInfoTLV *tlv)
|
||||
{
|
||||
int count = 0;
|
||||
int i;
|
||||
|
||||
if (!csm || !tlv)
|
||||
return MCLAG_ERROR;
|
||||
count = ntohs(tlv->num_of_entry);
|
||||
ICCPD_LOG_INFO(__FUNCTION__, "Received NDISC Info count %d ", count);
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
mlacp_fsm_update_ndisc_entry(csm, &(tlv->NdiscEntry[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************
|
||||
* Port-Channel-Info Update
|
||||
* ***************************************/
|
||||
@ -703,10 +909,10 @@ int mlacp_fsm_update_peerlink_info(struct CSM* csm,
|
||||
}
|
||||
|
||||
if (csm->peer_link_if->type != tlv->port_type)
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port type of peer %d is not same with local %d !", tlv->port_type, csm->peer_link_if->type);
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peerlink port type of peer %d is not same with local %d !", tlv->port_type, csm->peer_link_if->type);
|
||||
|
||||
if (tlv->port_type == IF_T_VXLAN && strncmp(csm->peer_itf_name, tlv->if_name, strlen(csm->peer_itf_name)))
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Peerlink port is vxlan port, but peerlink port of peer %s is not same with local %s !", tlv->if_name, csm->peer_itf_name);
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Peerlink port is vxlan port, but peerlink port of peer %s is not same with local %s !", tlv->if_name, csm->peer_itf_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -733,7 +939,7 @@ int mlacp_fsm_update_warmboot(struct CSM* csm, struct mLACPWarmbootTLV* tlv)
|
||||
return MCLAG_ERROR;
|
||||
|
||||
time(&csm->peer_warm_reboot_time);
|
||||
ICCPD_LOG_DEBUG(__FUNCTION__, "Receive warm reboot notification from peer!");
|
||||
ICCPD_LOG_NOTICE(__FUNCTION__, "Receive warm reboot notification from peer!");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -329,11 +329,12 @@ void local_if_destroy(char *ifname)
|
||||
int local_if_is_l3_mode(struct LocalInterface* local_if)
|
||||
{
|
||||
int ret = 0;
|
||||
char addr_null[16] = { 0 };
|
||||
|
||||
if (local_if == NULL)
|
||||
return 0;
|
||||
|
||||
if (local_if->ipv4_addr != 0)
|
||||
if (local_if->ipv4_addr != 0 || memcmp(local_if->ipv6_addr, addr_null, 16) != 0)
|
||||
ret = 1;
|
||||
|
||||
return ret;
|
||||
|
@ -312,7 +312,7 @@ void scheduler_init()
|
||||
iccp_config_from_file(sys->config_file_path);
|
||||
|
||||
/*Get kernel ARP info */
|
||||
iccp_arp_get_init();
|
||||
iccp_neigh_get_init();
|
||||
|
||||
if (iccp_connect_syncd() < 0)
|
||||
{
|
||||
|
@ -57,6 +57,7 @@ void system_init(struct System* sys)
|
||||
sys->sync_fd = -1;
|
||||
sys->sync_ctrl_fd = -1;
|
||||
sys->arp_receive_fd = -1;
|
||||
sys->ndisc_receive_fd = -1;
|
||||
sys->epoll_fd = -1;
|
||||
sys->family = -1;
|
||||
sys->warmboot_start = 0;
|
||||
@ -132,6 +133,8 @@ void system_finalize()
|
||||
close(sys->sync_ctrl_fd);
|
||||
if (sys->arp_receive_fd > 0)
|
||||
close(sys->arp_receive_fd);
|
||||
if (sys->ndisc_receive_fd > 0)
|
||||
close(sys->ndisc_receive_fd);
|
||||
if (sys->sig_pipe_r > 0)
|
||||
close(sys->sig_pipe_r);
|
||||
if (sys->sig_pipe_w > 0)
|
||||
|
Loading…
Reference in New Issue
Block a user