in src/iccpd/src/mlacp_sync_update.c [216:553]
int mlacp_fsm_update_mac_entry_from_peer( struct CSM* csm, struct mLACPMACData *MacData)
{
struct Msg* msg = NULL;
struct MACMsg *mac_msg = NULL, *new_mac_msg = NULL;
struct MACMsg mac_data, mac_find;
struct LocalInterface* local_if = NULL;
uint8_t from_mclag_intf = 0;/*0: orphan port, 1: MCLAG port*/
memset(&mac_data, 0, sizeof(struct MACMsg));
memset(&mac_find, 0, sizeof(struct MACMsg));
uint8_t null_mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
ICCPD_LOG_INFO("ICCP_FDB",
"Received MAC Info, interface=[%s] vid[%d] MAC[%s] OperType[%s] MacType[%d] ",
MacData->ifname, ntohs(MacData->vid), mac_addr_to_str(MacData->mac_addr),
MacData->type == MAC_SYNC_ADD ? "add" : "del", MacData->mac_type);
if (memcmp(MacData->mac_addr, null_mac, ETHER_ADDR_LEN) == 0)
{
ICCPD_LOG_ERR(__FUNCTION__, "Invalid MAC address from peer do not add.");
return 0;
}
/*Find the interface in MCLAG interface list*/
LIST_FOREACH(local_if, &(MLACP(csm).lif_list), mlacp_next)
{
if (local_if->type == IF_T_PORT_CHANNEL && strcmp(local_if->name, MacData->ifname) == 0)
{
from_mclag_intf = 1;
break;
}
}
mac_find.vid = ntohs(MacData->vid);
memcpy(&mac_find.mac_addr, MacData->mac_addr, ETHER_ADDR_LEN);
mac_msg = RB_FIND(mac_rb_tree, &MLACP(csm).mac_rb ,&mac_find);
/*Same MAC is exist in local switch, this may be mac move*/
//if (strcmp(mac_msg->mac_str, MacData->mac_str) == 0 && mac_msg->vid == ntohs(MacData->vid))
if (mac_msg)
{
ICCPD_LOG_DEBUG("ICCP_FDB", "Recv MAC update from peer RB_FIND success, existing MAC age flag:%d interface %s, "
"MAC %s vlan-id %d, fdb_type: %d, op_type %s", mac_msg->age_flag, mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->fdb_type,
(mac_msg->op_type == MAC_SYNC_ADD) ? "add":"del");
if (MacData->type == MAC_SYNC_ADD)
{
mac_msg->age_flag &= ~MAC_AGE_PEER;
if (from_mclag_intf && mac_msg->pending_local_del)
{
mac_msg->pending_local_del = 0;
mac_msg->age_flag = MAC_AGE_LOCAL;
// AS MAC was learned locally and in pending state due to IF is down,
// send del to peer when MAC add received from peer
mac_msg->op_type = MAC_SYNC_DEL;
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
{
TAILQ_INSERT_TAIL(&(MLACP(csm).mac_msg_list), mac_msg, tail);
}
}
ICCPD_LOG_DEBUG("ICCP_FDB", "Recv ADD, Remove peer age flag:%d interface %s, "
"MAC %s vlan-id %d, op_type %s, from_mclag_intf: %d ", mac_msg->age_flag, mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid,
(mac_msg->op_type == MAC_SYNC_ADD) ? "add":"del", from_mclag_intf);
/*mac_msg->fdb_type = tlv->fdb_type;*/
/*The port ifname is different to the local item*/
if (strcmp(mac_msg->ifname, MacData->ifname) != 0 || strcmp(mac_msg->origin_ifname, MacData->ifname) != 0)
{
if (mac_msg->fdb_type != MAC_TYPE_STATIC)
{
/*Update local item*/
memcpy(&mac_msg->origin_ifname, MacData->ifname, MAX_L_PORT_NAME);
}
else
{
ICCPD_LOG_DEBUG("ICCP_FDB", "Ignore Recv MAC ADD, Local static present,"
" interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
//set back the peer age flag
mac_msg->age_flag |= MAC_AGE_PEER;
return 0;
}
/*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/
if (from_mclag_intf == 0 || local_if->state == PORT_STATE_DOWN )
{
/*Set MAC_AGE_LOCAL flag*/
mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1, 1);
if (strlen(csm->peer_itf_name) != 0)
{
if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0)
{
/*This MAC is already point to peer-link*/
ICCPD_LOG_NOTICE("ICCP_FDB", "Remote MAC ADD local IF down, MAC already points to Peer_link done processing "
" interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
return 0;
}
if (csm->peer_link_if && (csm->peer_link_if->state == PORT_STATE_UP))
{
/*Redirect the mac to peer-link*/
memcpy(&mac_msg->ifname, csm->peer_itf_name, MAX_L_PORT_NAME);
/*Send mac add message to mclagsyncd*/
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
ICCPD_LOG_DEBUG("ICCP_FDB", "Remote MAC ADD , local mac exist move to peer link up "
" interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
}
else
{
/*Redirect the mac to peer-link, if peerlink is down FdbOrch deletes MAC*/
memcpy(&mac_msg->ifname, csm->peer_itf_name, MAX_L_PORT_NAME);
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
ICCPD_LOG_DEBUG("ICCP_FDB", "Remote MAC ADD , local mac exist move to peer link down "
" interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
}
}
else
{
/*must redirect but no peerlink, del mac from ASIC*/
del_mac_from_chip(mac_msg);
/*Update local item*/
memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME);
/*if orphan port mac but no peerlink, don't keep this mac*/
if (from_mclag_intf == 0)
{
MAC_RB_REMOVE(mac_rb_tree, &MLACP(csm).mac_rb, mac_msg);
// free only if not in change list to be send to peer node,
// else free is taken care after sending the update to peer
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
{
free(mac_msg);
}
ICCPD_LOG_ERR(__FUNCTION__, "Ignore Recv MAC ADD "
"MAC %s vlan %d interface %s peer link not available ",
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->ifname);
return 0;
}
}
}
else
{
/*Update local item*/
memcpy(&mac_msg->ifname, MacData->ifname, MAX_L_PORT_NAME);
/*from MCLAG port and the local port is up, add mac to ASIC to update port*/
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
}
}
else if(!from_mclag_intf && (strcmp(mac_msg->ifname, MacData->ifname) == 0))
{
// local to remote MAC move on Orphan port.
if (strlen(csm->peer_itf_name) != 0)
{
if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0)
{
/*This MAC is already point to peer-link*/
ICCPD_LOG_DEBUG("ICCP_FDB", "Remote MAC ADD learn on Orphan port ,MAC already points to Peer_link"
" interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
return 0;
}
if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP)
{
/*Redirect the mac to peer-link*/
memcpy(&mac_msg->ifname, csm->peer_itf_name, MAX_L_PORT_NAME);
ICCPD_LOG_DEBUG("ICCP_FDB", "Remote MAC ADD learn on Orphan port ,point MAC address to Peer_link"
"interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
/*Send mac add message to mclagsyncd*/
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
}
else
{
/*Redirect the mac to peer-link*/
/*must redirect but if peerlink is down FdbOrch will delete MAC */
memcpy(&mac_msg->ifname, csm->peer_itf_name, MAX_L_PORT_NAME);
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
ICCPD_LOG_DEBUG("ICCP_FDB", "Remote MAC ADD learn on Orphan port ,point MAC address to Peer_link"
" peer link is down, delete the MAC, interface %s, MAC %s vlan-id %d ", mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid);
}
}
}
// Code to exchange MAC_SYNC_ACK notifications can be enabled in future, if MAC SYNC issues observed.
#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_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->op_type);
}
#endif
}
// Code to exchange MAC_SYNC_ACK notifications can be enabled in future, if MAC SYNC issues observed.
#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_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->op_type);
}
#endif
}
/* delete/add MAC list*/
if (mac_msg && (MacData->type == MAC_SYNC_DEL))
{
mac_msg->age_flag |= MAC_AGE_PEER;
ICCPD_LOG_DEBUG("ICCP_FDB", "Recv MAC DEL from peer: Add peer age flag: %d interface %s, "
"MAC %s vlan %d, op_type %s", mac_msg->age_flag, mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr), mac_msg->vid,
(mac_msg->op_type == MAC_SYNC_ADD) ? "add":"del");
if (mac_msg->age_flag == (MAC_AGE_LOCAL | MAC_AGE_PEER))
{
/*send mac del message to mclagsyncd.*/
del_mac_from_chip(mac_msg);
/*If local and peer both aged, del the mac*/
MAC_RB_REMOVE(mac_rb_tree, &MLACP(csm).mac_rb, mac_msg);
// free only if not in change list to be send to peer node,
// else free is taken care after sending the update to peer
if (!MAC_IN_MSG_LIST(&(MLACP(csm).mac_msg_list), mac_msg, tail))
{
free(mac_msg);
}
}
else
{
return 0;
}
}
else if (!mac_msg && (MacData->type == MAC_SYNC_ADD))
{
mac_msg = (struct MACMsg*)&mac_data;
mac_msg->fdb_type = MacData->mac_type;
mac_msg->vid = ntohs(MacData->vid);
memcpy(mac_msg->mac_addr, MacData->mac_addr, ETHER_ADDR_LEN);
sprintf(mac_msg->ifname, "%s", MacData->ifname);
sprintf(mac_msg->origin_ifname, "%s", MacData->ifname);
mac_msg->age_flag = 0;
/*Set MAC_AGE_LOCAL flag*/
mac_msg->age_flag = set_mac_local_age_flag(csm, mac_msg, 1, 0);
/*If the MAC is learned from orphan port, or from MCLAG port but the local port is down*/
if (from_mclag_intf == 0 || local_if->state == PORT_STATE_DOWN)
{
if (strlen(csm->peer_itf_name) == 0)
{
/*if orphan port mac but no peerlink, don't keep this mac*/
//MAC to be saved and program when peer_link is configured..? TBD
if (from_mclag_intf == 0)
{
ICCPD_LOG_DEBUG("ICCP_FDB", "Recv MAC ADD from peer: Ignore MAC learn on orphan port "
"peer-link is not configured interface %s, MAC %s vlan-id %d, "
" op_type %d", from_mclag_intf, mac_msg->ifname,
mac_addr_to_str(mac_msg->mac_addr),
mac_msg->vid, mac_msg->op_type);
return 0;
}
}
else
{
/*Redirect the mac to peer-link*/
memcpy(&mac_msg->ifname, csm->peer_itf_name, MAX_L_PORT_NAME);
ICCPD_LOG_DEBUG("ICCP_FDB", "Recv MAC ADD from peer: Redirect to peerlink for orphan port or portchannel is down,"
" age flag: %d interface %s, MAC %s vlan %d, op_type %d",
mac_msg->age_flag, mac_msg->ifname, mac_addr_to_str(mac_msg->mac_addr),
mac_msg->vid, mac_msg->op_type);
}
}
if (iccp_csm_init_mac_msg(&new_mac_msg, (char*)mac_msg, sizeof(struct MACMsg)) == 0)
{
/*ICCPD_LOG_INFO(__FUNCTION__, "add mac queue successfully");*/
RB_INSERT(mac_rb_tree, &MLACP(csm).mac_rb, new_mac_msg);
/*If the mac is from orphan port, or from MCLAG port but the local port is down*/
if (strcmp(mac_msg->ifname, csm->peer_itf_name) == 0)
{
/*Send mac add message to mclagsyncd*/
if (csm->peer_link_if && csm->peer_link_if->state == PORT_STATE_UP)
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
}
else if(local_if->state != PORT_STATE_DOWN)
{
/*from MCLAG port and the local port is up*/
add_mac_to_chip(mac_msg, mac_msg->fdb_type);
}
// Code to exchange MAC_SYNC_ACK notifications can be enabled in future, if MAC SYNC issues observed.
#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_addr_to_str(mac_msg->mac_addr), mac_msg->vid, mac_msg->op_type);
}
#endif
}
}
return 0;
}