[iccpd]: ICCPD support IPv6 ND (#4422)

accomplish it according MCLAG HLD document, the principle is similar to IPv4 ARP.
This commit is contained in:
jianjundong 2020-04-30 02:10:35 +08:00 committed by GitHub
parent 087e5fbf78
commit 4c55adfd6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1606 additions and 480 deletions

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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)