diff --git a/mclagsyncd/mclag.h b/mclagsyncd/mclag.h index 066b919862..7a7fa7308f 100644 --- a/mclagsyncd/mclag.h +++ b/mclagsyncd/mclag.h @@ -23,13 +23,31 @@ #define MCLAG_DEFAULT_IP 0x7f000006 enum MCLAG_FDB_OP_TYPE { - MCLAG_FDB_OPER_ADD =1, + MCLAG_FDB_OPER_ADD = 1, MCLAG_FDB_OPER_DEL = 2, }; enum MCLAG_FDB_TYPE { - MCLAG_FDB_TYPE_STATIC = 1, + MCLAG_FDB_TYPE_STATIC = 1, MCLAG_FDB_TYPE_DYNAMIC = 2, + MCLAG_FDB_TYPE_DYNAMIC_LOCAL = 3, /* Used while sending MAC to Syncd to program with aging enabled. */ +}; + +enum MCLAG_DOMAIN_CFG_OP_TYPE { + MCLAG_CFG_OPER_NONE = 0, //NOP + MCLAG_CFG_OPER_ADD = 1, //Add domain + MCLAG_CFG_OPER_DEL = 2, //Delete domain + MCLAG_CFG_OPER_UPDATE = 3, //update domain + MCLAG_CFG_OPER_ATTR_DEL = 4 //Attribute del +}; + +enum MCLAG_DOMAIN_CFG_ATTR_BMAP_FLAGS { + MCLAG_CFG_ATTR_NONE = 0x0, + MCLAG_CFG_ATTR_SRC_ADDR = 0x1, + MCLAG_CFG_ATTR_PEER_ADDR = 0x2, + MCLAG_CFG_ATTR_PEER_LINK = 0x4, + MCLAG_CFG_ATTR_KEEPALIVE_INTERVAL = 0x8, + MCLAG_CFG_ATTR_SESSION_TIMEOUT = 0x10 }; /* @@ -66,7 +84,11 @@ typedef struct mclag_msg_hdr_t_ { /*syncd send msg type to iccpd*/ typedef enum mclag_syncd_msg_type_e_ { MCLAG_SYNCD_MSG_TYPE_NONE = 0, - MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1 + MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION = 1, + MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN = 2, + MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE = 3, + MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES = 4, + MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP = 5 }mclag_syncd_msg_type_e; /*iccpd send msg type to syncd*/ @@ -77,8 +99,16 @@ typedef enum mclag_msg_type_e_ { MCLAG_MSG_TYPE_FLUSH_FDB = 3, MCLAG_MSG_TYPE_SET_INTF_MAC = 4, MCLAG_MSG_TYPE_SET_FDB = 5, - MCLAG_MSG_TYPE_FLUSH_FDB_BY_PORT = 6, - MCLAG_MSG_TYPE_GET_FDB_CHANGES = 20 + MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_ENABLE = 6, + MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE = 7, + MCLAG_MSG_TYPE_SET_ICCP_STATE = 8, + MCLAG_MSG_TYPE_SET_ICCP_ROLE = 9, + MCLAG_MSG_TYPE_SET_ICCP_SYSTEM_ID = 10, + MCLAG_MSG_TYPE_DEL_ICCP_INFO = 11, + MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE = 12, + MCLAG_MSG_TYPE_DEL_REMOTE_IF_INFO = 13, + MCLAG_MSG_TYPE_SET_PEER_LINK_ISOLATION = 14, + MCLAG_MSG_TYPE_SET_ICCP_PEER_SYSTEM_ID = 15 }mclag_msg_type_e; typedef struct mclag_sub_option_hdr_t_ { @@ -88,6 +118,7 @@ typedef struct mclag_sub_option_hdr_t_ { * Length of option value, not including the header. */ uint16_t op_len; + uint8_t data[]; }mclag_sub_option_hdr_t; #define MCLAG_SUB_OPTION_HDR_LEN (sizeof (mclag_sub_option_hdr_t)) @@ -99,7 +130,14 @@ typedef enum mclag_sub_option_type_e_ { MCLAG_SUB_OPTION_TYPE_MAC_LEARN_ENABLE = 3, MCLAG_SUB_OPTION_TYPE_MAC_LEARN_DISABLE = 4, MCLAG_SUB_OPTION_TYPE_SET_MAC_SRC = 5, - MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6 + MCLAG_SUB_OPTION_TYPE_SET_MAC_DST = 6, + MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME = 7, + MCLAG_SUB_OPTION_TYPE_MCLAG_ID = 8, + MCLAG_SUB_OPTION_TYPE_ICCP_ROLE = 9, + MCLAG_SUB_OPTION_TYPE_SYSTEM_ID = 10, + MCLAG_SUB_OPTION_TYPE_OPER_STATUS = 11, + MCLAG_SUB_OPTION_TYPE_ISOLATION_STATE = 12, + MCLAG_SUB_OPTION_TYPE_PEER_SYSTEM_ID = 13 } mclag_sub_option_type_e; static inline size_t @@ -162,3 +200,4 @@ mclag_msg_ok (const mclag_msg_hdr_t *hdr, size_t len) #endif + diff --git a/mclagsyncd/mclaglink.cpp b/mclagsyncd/mclaglink.cpp index 80353b0226..7e7a9aff27 100644 --- a/mclagsyncd/mclaglink.cpp +++ b/mclagsyncd/mclaglink.cpp @@ -24,6 +24,7 @@ #include #include #include "logger.h" +#include "tokenize.h" #include "netmsg.h" #include "netdispatcher.h" #include "swss/notificationproducer.h" @@ -31,10 +32,34 @@ #include "mclagsyncd/mclag.h" #include #include +#include "macaddress.h" +#include +#include +#include +#include +#include "table.h" using namespace swss; using namespace std; +void MclagLink::addVlanMbr(std::string vlan, std::string mbr_port) +{ + m_vlan_mbrship.emplace(vlan_mbr(vlan,mbr_port)); +} + +//returns 1 if present, else returns zero +int MclagLink::findVlanMbr(std::string vlan, std::string mbr_port) +{ + return (m_vlan_mbrship.find(vlan_mbr(vlan,mbr_port)) != m_vlan_mbrship.end()); +} + + +void MclagLink::delVlanMbr(std::string vlan, std::string mbr_port) +{ + m_vlan_mbrship.erase(vlan_mbr(vlan,mbr_port)); +} + + void MclagLink::getOidToPortNameMap(std::unordered_map & port_map) { auto hash = p_counters_db->hgetall("COUNTERS_PORT_NAME_MAP"); @@ -87,163 +112,258 @@ void MclagLink::getVidByBvid(std::string &bvid, std::string &vlanid) return; } -void MclagLink::getFdbSet(std::set *fdb_set) +void MclagLink::mclagsyncdFetchSystemMacFromConfigdb() { - string bvid; - string bri_port_id; - string port_name; - string mac; - string type; - string vlanid; - int vid; - size_t pos1 = 0; - size_t pos2 = 0; - std::unordered_map oid_to_portname_map; - std::map brPortId_to_attrPortId_map; - std::map::iterator brPortId_to_attrPortId_it; + vector fvs; + p_device_metadata_tbl->get("localhost",fvs); + auto it = find_if(fvs.begin(), fvs.end(), [](const FieldValueTuple &fv) { + return fv.first == "mac"; + }); - auto keys = p_asic_db->keys("ASIC_STATE:SAI_OBJECT_TYPE_FDB_ENTRY:*"); - for (auto& key : keys) + if (it == fvs.end()) { - /*get vid*/ - pos1 = key.find("vlan", 0); - if (pos1 != key.npos) - { - pos1 = pos1 + 7; - pos2 = key.find(",", pos1) - 2; - vlanid = key.substr(pos1, pos2 - pos1 + 1); - } - else - { - pos1 = key.find("oid:", 0); - pos2 = key.find(",", 0) - 2; - bvid = key.substr(pos1, pos2 - pos1 + 1); - getVidByBvid(bvid, vlanid); - } - - vid = atoi(vlanid.c_str()); - /*get mac*/ - pos1 = key.find("mac", 0) + 6; - pos2 = key.find(",", pos1) - 2; - mac = key.substr(pos1, pos2 - pos1 + 1); + SWSS_LOG_ERROR("mclagsyncd: Failed to get MAC address from configuration database"); + return; + } - /*get type*/ - auto hash = p_asic_db->hgetall(key); - auto type_it = hash.find("SAI_FDB_ENTRY_ATTR_TYPE"); - if (type_it == hash.end()) - { - continue; - } + m_system_mac = it->second; + SWSS_LOG_NOTICE("mclagysncd: system_mac:%s ",m_system_mac.c_str()); + return; +} - if (memcmp(type_it->second.c_str(), "SAI_FDB_ENTRY_TYPE_DYNAMIC", type_it->second.length()) == 0) - type = "dynamic"; - else - type = "static"; - /*get port name*/ - getOidToPortNameMap(oid_to_portname_map); - getBridgePortIdToAttrPortIdMap(&brPortId_to_attrPortId_map); - auto brPortId_it = hash.find("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"); - if (brPortId_it == hash.end()) - { - continue; - } - bri_port_id = brPortId_it->second; +void MclagLink::mclagsyncdFetchMclagConfigFromConfigdb() +{ + TableDump mclag_cfg_dump; + SWSS_LOG_NOTICE("mclag cfg dump...."); + p_mclag_cfg_table->dump(mclag_cfg_dump); - brPortId_to_attrPortId_it = brPortId_to_attrPortId_map.find(bri_port_id); - if (brPortId_to_attrPortId_it == brPortId_to_attrPortId_map.end()) - { - continue; - } - auto oid_to_portName_it = oid_to_portname_map.find(brPortId_to_attrPortId_it->second); - if (oid_to_portName_it == oid_to_portname_map.end()) - { - continue; + std::deque entries; + for (const auto&key: mclag_cfg_dump) + { + KeyOpFieldsValuesTuple cfgentry; + SWSS_LOG_NOTICE("Key: %s", key.first.c_str()); + kfvKey(cfgentry) = key.first; + kfvOp(cfgentry) = "SET"; + SWSS_LOG_NOTICE("Value:"); + for (const auto& val : key.second) { + SWSS_LOG_NOTICE("%s: %s", val.first.c_str(), val.second.c_str()); + FieldValueTuple value; + fvField(value) = val.first; + fvValue(value) = val.second; + kfvFieldsValues(cfgentry).push_back(value); } + entries.push_back(cfgentry); + processMclagDomainCfg(entries); + } +} - port_name = oid_to_portName_it->second; +void MclagLink::mclagsyncdFetchMclagInterfaceConfigFromConfigdb() +{ + TableDump mclag_intf_cfg_dump; + SWSS_LOG_NOTICE("mclag cfg dump...."); + p_mclag_intf_cfg_table->dump(mclag_intf_cfg_dump); - /*insert set*/ - SWSS_LOG_DEBUG("Read one fdb entry(MAC:%s, vid:%d, port_name:%s, type:%s) from ASIC_DB and insert new_set.", mac.c_str(), vid, port_name.c_str(), type.c_str()); - fdb_set->insert(mclag_fdb(mac, vid, port_name, type)); + std::deque entries; + for (const auto&key: mclag_intf_cfg_dump) + { + KeyOpFieldsValuesTuple cfgentry; + SWSS_LOG_NOTICE("Key: %s", key.first.c_str()); + kfvKey(cfgentry) = key.first; + kfvOp(cfgentry) = "SET"; + SWSS_LOG_NOTICE("Value:"); + for (const auto& val : key.second) { + SWSS_LOG_NOTICE("%s: %s", val.first.c_str(), val.second.c_str()); + FieldValueTuple value; + fvField(value) = val.first; + fvValue(value) = val.second; + kfvFieldsValues(cfgentry).push_back(value); + } + entries.push_back(cfgentry); + mclagsyncdSendMclagIfaceCfg(entries); } - - return; } void MclagLink::setPortIsolate(char *msg) { - mclag_sub_option_hdr_t *op_hdr = NULL; - string isolate_src_port; - string isolate_dst_port; - char * cur = NULL; - string acl_name = "mclag"; - string acl_rule_name = "mclag:mclag"; - vector acl_attrs; - vector acl_rule_attrs; - std::string acl_key = std::string("") + APP_ACL_TABLE_TABLE_NAME + ":" + acl_name; - std::string acl_rule_key = std::string("") + APP_ACL_RULE_TABLE_NAME + ":" + acl_rule_name; - static int acl_table_is_added = 0; + char *platform = getenv("platform"); + if ((NULL != platform) && (strstr(platform, BRCM_PLATFORM_SUBSTRING))) + { + mclag_sub_option_hdr_t *op_hdr = NULL; + string isolate_src_port; + string isolate_dst_port; + char * cur = NULL; + vector fvts; - cur = msg; + cur = msg; - /*get isolate src port infor*/ - op_hdr = reinterpret_cast(static_cast(cur)); - cur = cur + MCLAG_SUB_OPTION_HDR_LEN; - isolate_src_port.insert(0, (const char*)cur, op_hdr->op_len); - cur = cur + op_hdr->op_len; + /*get isolate src port infor*/ + op_hdr = reinterpret_cast(static_cast(cur)); + cur = cur + MCLAG_SUB_OPTION_HDR_LEN; + isolate_src_port.insert(0, (const char*)cur, op_hdr->op_len); - /*get isolate dst ports infor*/ - op_hdr = reinterpret_cast(static_cast(cur)); - cur = cur + MCLAG_SUB_OPTION_HDR_LEN; - isolate_dst_port.insert(0, (const char*)cur, op_hdr->op_len); + cur = cur + op_hdr->op_len; - if (op_hdr->op_len == 0) - { - /* If dst port is NULL, delete the acl table 'mclag' */ - p_acl_table_tbl->del(acl_name); - acl_table_is_added = 0; - SWSS_LOG_DEBUG("Disable port isolate, src port: %s, dst port is NULL", - isolate_src_port.c_str()); - return; - } + /*get isolate dst ports infor*/ + op_hdr = reinterpret_cast(static_cast(cur)); + cur = cur + MCLAG_SUB_OPTION_HDR_LEN; - SWSS_LOG_DEBUG("Set port isolate, src port: %s, dst port: %s", - isolate_src_port.c_str(), isolate_dst_port.c_str()); - if (acl_table_is_added == 0) - { - /*First create ACL table*/ - FieldValueTuple desc_attr("policy_desc", "Mclag egress port isolate acl"); - acl_attrs.push_back(desc_attr); + if (op_hdr->op_len == 0) + { + /*Destination port can be empty when all remote MLAG interfaces + * goes down down or ICCP session goes down. Do not delete the + * isolation group when all remote interfaces are down. Just remove + * all destination ports from the group + */ + + if (is_iccp_up) + { + fvts.emplace_back("DESCRIPTION", "Isolation group for MCLAG"); + fvts.emplace_back("TYPE", "bridge-port"); + fvts.emplace_back("PORTS", isolate_src_port); + fvts.emplace_back("MEMBERS", isolate_dst_port); + p_iso_grp_tbl->set("MCLAG_ISO_GRP", fvts); + SWSS_LOG_NOTICE("Delete all isolation group destination ports"); + } + else + { + p_iso_grp_tbl->del("MCLAG_ISO_GRP"); + SWSS_LOG_NOTICE("Isolation group deleted"); + } + } + else + { + string temp; - FieldValueTuple type_attr("type", "MCLAG"); - acl_attrs.push_back(type_attr); + isolate_dst_port.insert(0, (const char*)cur, op_hdr->op_len); + istringstream dst_ss(isolate_dst_port); - FieldValueTuple port_attr("ports", isolate_src_port); - acl_attrs.push_back(port_attr); + isolate_dst_port.clear(); + while (getline(dst_ss, temp, ',')) + { + if (0 == temp.find("Ethernet")) + { + continue; + } + if (isolate_dst_port.length()) + { + isolate_dst_port = isolate_dst_port + ',' + temp; + } + else + { + isolate_dst_port = temp; + } + } - p_acl_table_tbl->set(acl_name, acl_attrs); + fvts.emplace_back("DESCRIPTION", "Isolation group for MCLAG"); + fvts.emplace_back("TYPE", "bridge-port"); + fvts.emplace_back("PORTS", isolate_src_port); + fvts.emplace_back("MEMBERS", isolate_dst_port); - acl_table_is_added = 1; - /*End create ACL table*/ + p_iso_grp_tbl->set("MCLAG_ISO_GRP", fvts); + SWSS_LOG_NOTICE("Isolation group created with ports %s and members %s", + isolate_src_port.c_str(), + isolate_dst_port.c_str()); + } } + else + { + mclag_sub_option_hdr_t *op_hdr = NULL; + string isolate_src_port; + string isolate_dst_port; + char * cur = NULL; + string acl_name = "mclag"; + string acl_rule_name = "mclag:mclag"; + vector acl_attrs; + vector acl_rule_attrs; + std::string acl_key = std::string("") + APP_ACL_TABLE_TABLE_NAME + ":" + acl_name; + std::string acl_rule_key = std::string("") + APP_ACL_RULE_TABLE_NAME + ":" + acl_rule_name; + static int acl_table_is_added = 0; + + cur = msg; + + /*get isolate src port infor*/ + op_hdr = reinterpret_cast(static_cast(cur)); + cur = cur + MCLAG_SUB_OPTION_HDR_LEN; + isolate_src_port.insert(0, (const char*)cur, op_hdr->op_len); + + cur = cur + op_hdr->op_len; + + /*get isolate dst ports infor*/ + op_hdr = reinterpret_cast(static_cast(cur)); + cur = cur + MCLAG_SUB_OPTION_HDR_LEN; + isolate_dst_port.insert(0, (const char*)cur, op_hdr->op_len); + + if (op_hdr->op_len == 0) + { + /* If dst port is NULL, delete the acl table 'mclag' */ + p_acl_table_tbl->del(acl_name); + acl_table_is_added = 0; + SWSS_LOG_NOTICE("set port isolate, src port: %s, dst port is NULL", + isolate_src_port.c_str()); + return; + } + + SWSS_LOG_NOTICE("set port isolate, src port: %s, dst port: %s", + isolate_src_port.c_str(), isolate_dst_port.c_str()); + + if (acl_table_is_added == 0) + { + /*First create ACL table*/ + FieldValueTuple desc_attr("policy_desc", "Mclag egress port isolate acl"); + acl_attrs.push_back(desc_attr); + + FieldValueTuple type_attr("type", "L3"); + acl_attrs.push_back(type_attr); + + FieldValueTuple port_attr("ports", isolate_src_port); + acl_attrs.push_back(port_attr); + + p_acl_table_tbl->set(acl_name, acl_attrs); + + acl_table_is_added = 1; + /*End create ACL table*/ + } + + /*Then create ACL rule table*/ + FieldValueTuple ip_type_attr("IP_TYPE", "ANY"); + acl_rule_attrs.push_back(ip_type_attr); + + string temp; + isolate_dst_port.insert(0, (const char*)cur, op_hdr->op_len); + istringstream dst_ss(isolate_dst_port); + + isolate_dst_port.clear(); + while (getline(dst_ss, temp, ',')) + { + if (0 == temp.find("PortChannel")) + { + continue; + } - /*Then create ACL rule table*/ - FieldValueTuple ip_type_attr("IP_TYPE", "ANY"); - acl_rule_attrs.push_back(ip_type_attr); + if (isolate_dst_port.length()) + { + isolate_dst_port = isolate_dst_port + ',' + temp; + } + else + { + isolate_dst_port = temp; + } + } - FieldValueTuple out_port_attr("OUT_PORTS", isolate_dst_port); - acl_rule_attrs.push_back(out_port_attr); + FieldValueTuple out_port_attr("OUT_PORTS", isolate_dst_port); + acl_rule_attrs.push_back(out_port_attr); - FieldValueTuple packet_attr("PACKET_ACTION", "DROP"); - acl_rule_attrs.push_back(packet_attr); + FieldValueTuple packet_attr("PACKET_ACTION", "DROP"); + acl_rule_attrs.push_back(packet_attr); - p_acl_rule_tbl->set(acl_rule_name, acl_rule_attrs); - /*End create ACL rule table*/ + p_acl_rule_tbl->set(acl_rule_name, acl_rule_attrs); + /*End create ACL rule table*/ + } return; } @@ -279,49 +399,29 @@ void MclagLink::setPortMacLearnMode(char *msg) p_lag_tbl->set(learn_port, attrs); /* vxlan tunnel is currently not supported, for src_ip is the mandatory attribute */ /* else if(strncmp(learn_port.c_str(),VXLAN_TUNNEL_PREFIX,5)==0) - p_tnl_tbl->set(learn_port, attrs); */ + p_tnl_tbl->set(learn_port, attrs); */ else p_port_tbl->set(learn_port, attrs); - SWSS_LOG_DEBUG("Set port mac learn mode, port: %s, learn-mode: %s", - learn_port.c_str(), learn_mode.c_str()); + SWSS_LOG_NOTICE("set port mac learn mode, port: %s, learn-mode: %s", + learn_port.c_str(), learn_mode.c_str()); return; } void MclagLink::setFdbFlush() { - swss::NotificationProducer flushFdb(p_appl_db, "FLUSHFDBREQUEST"); + swss::NotificationProducer flushFdb(p_appl_db.get(), "FLUSHFDBREQUEST"); vector values; - SWSS_LOG_DEBUG("Send fdb flush notification"); + SWSS_LOG_NOTICE("send fdb flush notification"); flushFdb.send("ALL", "ALL", values); return; } -void MclagLink::setFdbFlushByPort(char *msg) -{ - string port; - char *cur = NULL; - mclag_sub_option_hdr_t *op_hdr = NULL; - swss::NotificationProducer flushFdb(p_appl_db, "FLUSHFDBREQUEST"); - vector values; - - cur = msg; - /*get port infor*/ - op_hdr = reinterpret_cast(static_cast(cur)); - cur = cur + MCLAG_SUB_OPTION_HDR_LEN; - port.insert(0, (const char*)cur, op_hdr->op_len); - - SWSS_LOG_DEBUG("Send fdb flush by port %s notification", port.c_str()); - - flushFdb.send("ALL", port, values); - - return; -} void MclagLink::setIntfMac(char *msg) { @@ -344,7 +444,7 @@ void MclagLink::setIntfMac(char *msg) cur = cur + MCLAG_SUB_OPTION_HDR_LEN; mac_value.insert(0, (const char*)cur, op_hdr->op_len); - SWSS_LOG_DEBUG("Set mac to chip, intf key name: %s, mac: %s", intf_key.c_str(), mac_value.c_str()); + SWSS_LOG_NOTICE("set mac to chip, intf key name: %s, mac: %s", intf_key.c_str(), mac_value.c_str()); vector attrs; FieldValueTuple mac_attr("mac_addr", mac_value); attrs.push_back(mac_attr); @@ -362,34 +462,32 @@ void MclagLink::setFdbEntry(char *msg, int msg_len) char *cur = NULL; short count = 0; int index = 0; - int exist = 0; - set ::iterator it; - cur = msg; - count = (short)(msg_len / sizeof(struct mclag_fdb_info)); + cur = msg; + count = (short)(msg_len/sizeof(struct mclag_fdb_info)); - for (index = 0; index < count; index++) + for (index =0; index < count; index ++) { memset(key, 0, 64); fdb_info = reinterpret_cast(static_cast(cur + index * sizeof(struct mclag_fdb_info))); - fdb.mac = fdb_info->mac; + fdb.mac = MacAddress::to_string(fdb_info->mac); fdb.port_name = fdb_info->port_name; fdb.vid = fdb_info->vid; if (fdb_info->type == MCLAG_FDB_TYPE_STATIC) fdb.type = "static"; - else + else if (fdb_info->type == MCLAG_FDB_TYPE_DYNAMIC) fdb.type = "dynamic"; + else if (fdb_info->type == MCLAG_FDB_TYPE_DYNAMIC_LOCAL) + fdb.type = "dynamic_local"; - if ((it = find(p_old_fdb->begin(), p_old_fdb->end(), fdb)) == p_old_fdb->end()) - exist = 0; - else - exist = 1; - - snprintf(key, 64, "%s%d:%s", "Vlan", fdb_info->vid, fdb_info->mac); + snprintf(key, 64, "%s%d:%s", "Vlan", fdb_info->vid, fdb.mac.c_str()); fdb_key = key; + SWSS_LOG_DEBUG("Received MAC key: %s, op_type: %d, mac type: %s , port: %s", + fdb_key.c_str(), fdb_info->op_type, fdb.type.c_str(), fdb.port_name.c_str()); + if (fdb_info->op_type == MCLAG_FDB_OPER_ADD) { vector attrs; @@ -401,271 +499,1385 @@ void MclagLink::setFdbEntry(char *msg, int msg_len) /*set type attr*/ FieldValueTuple type_attr("type", fdb.type); attrs.push_back(type_attr); - - if (exist == 0) - { - p_old_fdb->insert(fdb); - SWSS_LOG_DEBUG("Insert node(portname =%s, mac =%s, vid =%d, type =%s) into old_fdb_set", - fdb.port_name.c_str(), fdb.mac.c_str(), fdb.vid, fdb.type.c_str()); - } - else - { - if (it->port_name == fdb.port_name && it->type == fdb.type) - { - SWSS_LOG_DEBUG("All items of mac is same (mac =%s, vid =%d, portname :%s ==> %s, type:%s ==>%s), return.", - fdb.mac.c_str(), fdb.vid, it->port_name.c_str(), fdb.port_name.c_str(), it->type.c_str(), fdb.type.c_str()); - return; - } - SWSS_LOG_DEBUG("Modify node(mac =%s, vid =%d, portname :%s ==> %s, type:%s ==>%s)", - fdb.mac.c_str(), fdb.vid, it->port_name.c_str(), fdb.port_name.c_str(), it->type.c_str(), fdb.type.c_str()); - p_old_fdb->erase(it); - p_old_fdb->insert(fdb); - #if 0 - fdb_entry = &(*it); - fdb_entry->port_name = fdb.port_name; - fdb_entry->type = fdb.type; - #endif - } - p_fdb_tbl->set(fdb_key, attrs); - SWSS_LOG_DEBUG("Add fdb entry into ASIC_DB:key =%s, type =%s", fdb_key.c_str(), fdb.type.c_str()); + SWSS_LOG_NOTICE("add fdb entry into ASIC_DB:key =%s, type =%s", fdb_key.c_str(), fdb.type.c_str()); } else if (fdb_info->op_type == MCLAG_FDB_OPER_DEL) { - if (exist) - { - SWSS_LOG_DEBUG("Erase node(portname =%s, mac =%s, vid =%d, type =%s) from old_fdb_set", - it->port_name.c_str(), it->mac.c_str(), it->vid, it->type.c_str()); - p_old_fdb->erase(it); - } p_fdb_tbl->del(fdb_key); - SWSS_LOG_DEBUG("Del fdb entry from ASIC_DB:key =%s", fdb_key.c_str()); + SWSS_LOG_NOTICE("del fdb entry from ASIC_DB:key =%s", fdb_key.c_str()); } } - return; } -ssize_t MclagLink::getFdbChange(char *msg_buf) +void MclagLink::mclagsyncdSendFdbEntries(std::deque &entries) { - set new_fdb; - set del_fdb; - set add_fdb; + size_t infor_len = sizeof(mclag_msg_hdr_t); struct mclag_fdb_info info; mclag_msg_hdr_t * msg_head = NULL; + int count = 0; ssize_t write = 0; - size_t infor_len = 0; - char *infor_start = msg_buf; - set *p_new_fdb = &new_fdb; - del_fdb.clear(); - add_fdb.clear(); - p_new_fdb->clear(); + char *infor_start = m_messageBuffer_send; + + /* Nothing popped */ + if (entries.empty()) + { + return; + } + + for (auto entry: entries) + { + memset(&info, 0, sizeof(struct mclag_fdb_info)); + count++; + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); - infor_len = infor_len + sizeof(mclag_msg_hdr_t); + std::size_t delimiter = key.find_first_of(":"); + auto vlan_name = key.substr(0, delimiter); + const auto mac_address_str = key.substr(delimiter+1); + uint8_t mac_address[ETHER_ADDR_LEN]; - getFdbSet(p_new_fdb); + MacAddress::parseMacString(mac_address_str, mac_address); - set_difference(p_old_fdb->begin(), p_old_fdb->end(), p_new_fdb->begin(), - p_new_fdb->end(), inserter(del_fdb, del_fdb.begin())); - set_difference(p_new_fdb->begin(), p_new_fdb->end(), p_old_fdb->begin(), - p_old_fdb->end(), inserter(add_fdb, add_fdb.begin())); + info.vid = (unsigned int) stoi(vlan_name.substr(4)); + memcpy(info.mac, mac_address , ETHER_ADDR_LEN); - p_old_fdb->swap(*p_new_fdb); + if (op == "SET") + info.op_type = MCLAG_FDB_OPER_ADD; + else + info.op_type = MCLAG_FDB_OPER_DEL; - /*Remove the same item from del set, this may be MAC move*/ - auto itdel = del_fdb.begin(); - while (itdel != del_fdb.end()) - { - auto ittmp = itdel; - itdel++; - for (auto itadd = add_fdb.begin(); itadd != add_fdb.end(); itadd++) + for (auto i : kfvFieldsValues(entry)) { - if (ittmp->mac == itadd->mac && ittmp->vid == itadd->vid) + if (fvField(i) == "port") { - SWSS_LOG_DEBUG("Mac move: mac %s, vid %d, portname %s, type %s", - ittmp->mac.c_str(), ittmp->vid, ittmp->port_name.c_str(), ittmp->type.c_str()); - del_fdb.erase(ittmp); - break; + memcpy(info.port_name, fvValue(i).c_str(), fvValue(i).length()); + } + if (fvField(i) == "type") + { + if (fvValue(i) == "dynamic") + info.type = MCLAG_FDB_TYPE_DYNAMIC; + else if (fvValue(i) == "static") + info.type = MCLAG_FDB_TYPE_STATIC; + else + SWSS_LOG_ERROR("MCLAGSYNCD STATE FDB updates key=%s, invalid MAC type %s\n", key.c_str(), fvValue(i).c_str()); } } - } + SWSS_LOG_NOTICE("MCLAGSYNCD STATE FDB updates key=%s, operation=%s, type: %d, port: %s \n", + key.c_str(), op.c_str(), info.type, info.port_name); - for (auto it = del_fdb.begin(); it != del_fdb.end(); it++) - { if (MCLAG_MAX_SEND_MSG_LEN - infor_len < sizeof(struct mclag_fdb_info)) { msg_head = reinterpret_cast(static_cast(infor_start)); msg_head->version = 1; msg_head->msg_len = (unsigned short)infor_len; - msg_head->msg_type = MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION; + msg_head ->msg_type = MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION; - SWSS_LOG_DEBUG("Mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d", - msg_head->msg_len, msg_head->msg_type); + SWSS_LOG_DEBUG("mclagsycnd buffer full send msg to iccpd, msg_len =%d, msg_type =%d count : %d", + msg_head->msg_len, msg_head->msg_type, count); write = ::write(m_connection_socket, infor_start, msg_head->msg_len); - if (write <= 0) - return write; - - infor_len = sizeof(mclag_msg_hdr_t); - } - SWSS_LOG_DEBUG("Notify iccpd to del fdb_entry:mac:%s, vid:%d, portname:%s, type:%s", - it->mac.c_str(), it->vid, it->port_name.c_str(), it->type.c_str()); - memset(&info, 0, sizeof(struct mclag_fdb_info)); - info.op_type = MCLAG_FDB_OPER_DEL; - memcpy(info.mac, it->mac.c_str(), it->mac.length()); - info.vid = it->vid; - memcpy(info.port_name, it->port_name.c_str(), it->port_name.length()); - if (memcmp(it->type.c_str(), "SAI_FDB_ENTRY_TYPE_DYNAMIC", it->type.length()) == 0) - info.type = MCLAG_FDB_TYPE_DYNAMIC; - else - info.type = MCLAG_FDB_TYPE_STATIC; - - memcpy((char*)(infor_start + infor_len), (char*)&info, sizeof(struct mclag_fdb_info)); - infor_len = infor_len + sizeof(struct mclag_fdb_info); - } - - for (auto it = add_fdb.begin(); it != add_fdb.end(); it++) - { - if (MCLAG_MAX_SEND_MSG_LEN - infor_len < sizeof(struct mclag_fdb_info)) - { - msg_head = reinterpret_cast(static_cast(infor_start)); - msg_head->version = 1; - msg_head->msg_len = (unsigned short)infor_len; - msg_head->msg_type = MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION; - /*SWSS_LOG_DEBUG("Mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d", - msg_head->msg_len, msg_head->msg_type);*/ - write = ::write(m_connection_socket, infor_start, msg_head->msg_len); if (write <= 0) - return write; + { + SWSS_LOG_ERROR("mclagsycnd update FDB to ICCPD Buffer full, write to m_connection_socket failed"); + } infor_len = sizeof(mclag_msg_hdr_t); + count = 0; } - SWSS_LOG_DEBUG("Notify iccpd to add fdb_entry:mac:%s, vid:%d, portname:%s, type:%s", - it->mac.c_str(), it->vid, it->port_name.c_str(), it->type.c_str()); - memset(&info, 0, sizeof(struct mclag_fdb_info)); - info.op_type = MCLAG_FDB_OPER_ADD; - memcpy(info.mac, it->mac.c_str(), it->mac.length()); - info.vid = it->vid; - memcpy(info.port_name, it->port_name.c_str(), it->port_name.length()); - if (memcmp(it->type.c_str(), "dynamic", it->type.length()) == 0) - info.type = MCLAG_FDB_TYPE_DYNAMIC; - else - info.type = MCLAG_FDB_TYPE_STATIC; - memcpy((char*)(infor_start + infor_len), (char*)&info, sizeof(struct mclag_fdb_info)); infor_len = infor_len + sizeof(struct mclag_fdb_info); } + if (infor_len <= sizeof(mclag_msg_hdr_t)) /*no fdb entry need notifying iccpd*/ - return 1; + return; msg_head = reinterpret_cast(static_cast(infor_start)); + msg_head->version = 1; msg_head->msg_len = (unsigned short)infor_len; - msg_head->msg_type = MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION; + msg_head ->msg_type = MCLAG_SYNCD_MSG_TYPE_FDB_OPERATION; - /*SWSS_LOG_DEBUG("Mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d", - msg_head->msg_len, msg_head->msg_type);*/ + SWSS_LOG_DEBUG("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d", + msg_head->msg_len, msg_head->msg_type, count); write = ::write(m_connection_socket, infor_start, msg_head->msg_len); - return write; + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd update FDB to ICCPD, write to m_connection_socket failed"); + } + + return; } -MclagLink::MclagLink(uint16_t port) : - MSG_BATCH_SIZE(256), - m_bufSize(MCLAG_MAX_MSG_LEN * MSG_BATCH_SIZE), - m_messageBuffer(NULL), - m_pos(0), - m_connected(false), - m_server_up(false) + +void MclagLink::processMclagDomainCfg(std::deque &entries) { - struct sockaddr_in addr; - int true_val = 1; + char *infor_start = getSendMsgBuffer(); + size_t infor_len = sizeof(mclag_msg_hdr_t); + uint8_t system_mac[ETHER_ADDR_LEN]; + int add_cfg_dependent_selectables = 0; - m_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (m_server_socket < 0) - throw system_error(errno, system_category()); + int count = 0; + ssize_t write = 0; - if (setsockopt(m_server_socket, SOL_SOCKET, SO_REUSEADDR, &true_val, - sizeof(true_val)) < 0) - { - close(m_server_socket); - throw system_error(errno, system_category()); - } + struct mclag_domain_cfg_info cfg_info; + mclag_msg_hdr_t *cfg_msg_hdr = NULL; - if (setsockopt(m_server_socket, SOL_SOCKET, SO_KEEPALIVE, &true_val, - sizeof(true_val)) < 0) + /* Nothing popped */ + if (entries.empty()) { - close(m_server_socket); - throw system_error(errno, system_category()); + return; } - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(MCLAG_DEFAULT_IP); - - if (bind(m_server_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) - { - close(m_server_socket); - throw system_error(errno, system_category()); - } + MacAddress::parseMacString(m_system_mac, system_mac); - if (listen(m_server_socket, 2) != 0) + for (auto entry: entries) { - close(m_server_socket); - throw system_error(errno, system_category()); - } - m_server_up = true; - m_messageBuffer = new char[m_bufSize]; - m_messageBuffer_send = new char[MCLAG_MAX_SEND_MSG_LEN]; -} + std::string domain_id_str = kfvKey(entry); + std::string op = kfvOp(entry); + int entryExists = 0; + int attrBmap = MCLAG_CFG_ATTR_NONE; + int attrDelBmap = MCLAG_CFG_ATTR_NONE; + enum MCLAG_DOMAIN_CFG_OP_TYPE cfgOpType = MCLAG_CFG_OPER_NONE; -MclagLink::~MclagLink() -{ - delete[] m_messageBuffer; - delete[] m_messageBuffer_send; - if (m_connected) - close(m_connection_socket); - if (m_server_up) - close(m_server_socket); -} + memset(&cfg_info, 0, sizeof(mclag_domain_cfg_info)); + cfg_info.domain_id = stoi(domain_id_str); + memcpy(cfg_info.system_mac, system_mac, ETHER_ADDR_LEN); -void MclagLink::accept() -{ - struct sockaddr_in client_addr; - socklen_t client_len; - m_connection_socket = ::accept(m_server_socket, (struct sockaddr *)&client_addr, - &client_len); - if (m_connection_socket < 0) - throw system_error(errno, system_category()); + SWSS_LOG_INFO("Key(mclag domain_id):%s; op:%s ", domain_id_str.c_str(), op.c_str()); - SWSS_LOG_NOTICE("New connection accepted from: %s", inet_ntoa(client_addr.sin_addr)); -} + const struct mclagDomainEntry domain(stoi(domain_id_str)); + auto it = m_mclag_domains.find(domain); + if (it != m_mclag_domains.end()) + { + entryExists = 1; + } -int MclagLink::getFd() -{ - return m_connection_socket; -} + if (op == "SET") + { + struct mclagDomainData domainData; -uint64_t MclagLink::readData() -{ - mclag_msg_hdr_t *hdr = NULL; - size_t msg_len = 0; - size_t start = 0, left = 0; - ssize_t read = 0; - ssize_t write = 0; - char * msg = NULL; + for (auto i : kfvFieldsValues(entry)) + { + SWSS_LOG_DEBUG(" MCLAGSYNCD CFG Table Updates : " "Field %s, Value: %s EntryExits:%d \n", + fvField(i).c_str(), fvValue(i).c_str(), entryExists); - read = ::read(m_connection_socket, m_messageBuffer + m_pos, m_bufSize - m_pos); - if (read == 0) - throw MclagConnectionClosedException(); - if (read < 0) - throw system_error(errno, system_category()); - m_pos += (uint32_t)read; + if (fvField(i) == "source_ip") + { + domainData.source_ip = fvValue(i); + + if(!entryExists) + { + attrBmap = (attrBmap | MCLAG_CFG_ATTR_SRC_ADDR); + memcpy(cfg_info.local_ip, domainData.source_ip.c_str(), INET_ADDRSTRLEN); + } + } + if (fvField(i) == "peer_ip") + { + domainData.peer_ip = fvValue(i); + if(!entryExists) + { + attrBmap = (attrBmap | MCLAG_CFG_ATTR_PEER_ADDR); + memcpy(cfg_info.peer_ip, domainData.peer_ip.c_str(), INET_ADDRSTRLEN); + } + } + if (fvField(i) == "peer_link") + { + domainData.peer_link = fvValue(i); + if(!entryExists) + { + attrBmap = (attrBmap | MCLAG_CFG_ATTR_PEER_LINK); + memcpy(cfg_info.peer_ifname, domainData.peer_link.c_str(), MAX_L_PORT_NAME); + } + } + if (fvField(i) == "keepalive_interval") + { + if (fvValue(i).empty()) + { + domainData.keepalive_interval = -1; + } + else + { + domainData.keepalive_interval = stoi(fvValue(i).c_str()); + } + if(!entryExists) + { + attrBmap = (attrBmap | MCLAG_CFG_ATTR_KEEPALIVE_INTERVAL); + cfg_info.keepalive_time = domainData.keepalive_interval; + } + } + if (fvField(i) == "session_timeout") + { + if (fvValue(i).empty()) + { + domainData.session_timeout = -1; + } + else + { + domainData.session_timeout = stoi(fvValue(i).c_str()); + } + if(!entryExists) + { + attrBmap = (attrBmap | MCLAG_CFG_ATTR_SESSION_TIMEOUT); + cfg_info.session_timeout = domainData.session_timeout; + } + } + } + + + //If entry present send only the diff + if (entryExists) + { + if( (it->second.source_ip.compare(domainData.source_ip)) != 0) + { + attrBmap = (attrBmap | MCLAG_CFG_ATTR_SRC_ADDR); + memcpy(cfg_info.local_ip, domainData.source_ip.c_str(), INET_ADDRSTRLEN); + if (domainData.source_ip.empty()) + { + attrDelBmap = attrDelBmap | MCLAG_CFG_ATTR_SRC_ADDR; + } + } + if( (it->second.peer_ip.compare(domainData.peer_ip)) != 0) + { + attrBmap |= MCLAG_CFG_ATTR_PEER_ADDR; + memcpy(cfg_info.peer_ip, domainData.peer_ip.c_str(), INET_ADDRSTRLEN); + + if (domainData.peer_ip.empty()) + { + attrDelBmap = attrDelBmap | MCLAG_CFG_ATTR_PEER_ADDR; + } + } + if( (it->second.peer_link.compare(domainData.peer_link)) != 0) + { + attrBmap |= MCLAG_CFG_ATTR_PEER_LINK; + memcpy(cfg_info.peer_ifname, domainData.peer_link.c_str(), MAX_L_PORT_NAME); + if (domainData.peer_link.empty()) + { + attrDelBmap = attrDelBmap | MCLAG_CFG_ATTR_PEER_LINK; + } + } + + if(it->second.keepalive_interval != domainData.keepalive_interval) + { + attrBmap |= MCLAG_CFG_ATTR_KEEPALIVE_INTERVAL; + cfg_info.keepalive_time = domainData.keepalive_interval; + if (domainData.keepalive_interval == -1) + { + attrDelBmap = attrDelBmap | MCLAG_CFG_ATTR_KEEPALIVE_INTERVAL; + } + } + + if(it->second.session_timeout != domainData.session_timeout) + { + attrBmap |= MCLAG_CFG_ATTR_SESSION_TIMEOUT; + cfg_info.session_timeout = domainData.session_timeout; + if (domainData.session_timeout == -1) + { + attrDelBmap = attrDelBmap | MCLAG_CFG_ATTR_SESSION_TIMEOUT; + } + } + } + + //nothing changed no need to update + if (!attrBmap && !attrDelBmap) + { + //no need to update + SWSS_LOG_NOTICE("mclagsycnd: domain cfg processing ; no change - duplicate update"); + return; + } + + SWSS_LOG_NOTICE("mclagsycnd: domain cfg processing; mandatory args present; Domain [%d] send to iccpd", domain.domain_id); + + //Add/update domain map + m_mclag_domains[domain] = domainData; + + //send config msg to iccpd + SWSS_LOG_DEBUG(" MCLAGSYNCD CFG Table Updates : domain_id:%d op_type:%d attrBmap:0x%x attrDelBmap:0x%x cfg_info.local_ip %s, peer_ip: %s peer_link:%s system_mac:%s session_timeout:%d keepalive_time:%d ", + domain.domain_id, cfgOpType, attrBmap, attrDelBmap, cfg_info.local_ip, cfg_info.peer_ip, cfg_info.peer_ifname, m_system_mac.c_str(), cfg_info.session_timeout, cfg_info.keepalive_time); + + //Entry not found previously and got created now - do add operation + if (!entryExists) + { + cfgOpType = MCLAG_CFG_OPER_ADD; + + add_cfg_dependent_selectables = 1; + } + else //entry found + { + //entry found and one attribute is deleted + if ( attrDelBmap && (attrBmap == attrDelBmap) ) + { + cfgOpType = MCLAG_CFG_OPER_ATTR_DEL; + } + else //entry found and attribute are getting updated + { + cfgOpType = MCLAG_CFG_OPER_UPDATE; + } + + } + } + else + { + //Entry not found - error deletion + if (!entryExists) + { + SWSS_LOG_WARN("mclagsycnd to ICCPD, cfg processing ; Domain [%d] deletion - domain not found", domain.domain_id); + return; + } + else + { + cfgOpType = MCLAG_CFG_OPER_DEL; + SWSS_LOG_NOTICE(" Del dependent selectables from select "); + delDomainCfgDependentSelectables(); + add_cfg_dependent_selectables = 0; + m_mclag_domains.erase(domain); + SWSS_LOG_NOTICE("mclagsycnd to ICCPD, cfg processing ; Domain [%d] deletion", domain.domain_id); + } + } + + if (cfgOpType == MCLAG_CFG_OPER_NONE) + { + SWSS_LOG_NOTICE("mclagsycnd to ICCPD, cfg processing ; Domain [%d] op type not set", domain.domain_id); + return; + } + + + if (MCLAG_MAX_SEND_MSG_LEN - infor_len < (sizeof(struct mclag_domain_cfg_info)) ) + { + cfg_msg_hdr = reinterpret_cast(static_cast(infor_start)); + cfg_msg_hdr->version = 1; + cfg_msg_hdr->msg_len = (unsigned short)infor_len; + cfg_msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN; + + SWSS_LOG_DEBUG("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d version=%d count : %d", cfg_msg_hdr->msg_len, cfg_msg_hdr->msg_type, cfg_msg_hdr->version, count); + write = ::write(getConnSocket(), infor_start, cfg_msg_hdr->msg_len); + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, domain cfg send, buffer full; write to m_connection_socket failed"); + } + + infor_len = sizeof(mclag_msg_hdr_t); + } + + cfg_info.op_type = cfgOpType; + cfg_info.attr_bmap = attrBmap; + memcpy((char*)(infor_start + infor_len), (char*)&cfg_info, sizeof(struct mclag_domain_cfg_info)); + infor_len = infor_len + sizeof(struct mclag_domain_cfg_info); + SWSS_LOG_DEBUG(" MCLAGSYNCD CFG Table Updates: domain_id:%d infor_len:%d infor_start:%p ", cfg_info.domain_id, (int)infor_len, infor_start); + } + + /*no config info notification reqd */ + if (infor_len <= sizeof(mclag_msg_hdr_t)) + return; + + cfg_msg_hdr = reinterpret_cast(static_cast(infor_start)); + cfg_msg_hdr->version = 1; + cfg_msg_hdr->msg_len = (unsigned short)infor_len; + cfg_msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_DOMAIN; + + SWSS_LOG_DEBUG("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d ver = %d ", cfg_msg_hdr->msg_len, cfg_msg_hdr->msg_type, count, cfg_msg_hdr->version); + write = ::write(getConnSocket(), infor_start, cfg_msg_hdr->msg_len); + + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, domain cfg send; write to m_connection_socket failed"); + } + + if (add_cfg_dependent_selectables) + { + SWSS_LOG_NOTICE(" Add dependent selectables to select "); + addDomainCfgDependentSelectables(); + } +} + +void MclagLink::addDomainCfgDependentSelectables() +{ + p_state_fdb_tbl = new SubscriberStateTable(p_state_db.get(), STATE_FDB_TABLE_NAME); + SWSS_LOG_INFO(" MCLAGSYNCD create state fdb table"); + + p_state_vlan_mbr_subscriber_table = new SubscriberStateTable(p_state_db.get(), STATE_VLAN_MEMBER_TABLE_NAME); + SWSS_LOG_INFO(" MCLAGSYNCD create state vlan member table"); + + p_mclag_intf_cfg_tbl = new SubscriberStateTable(p_config_db.get(), CFG_MCLAG_INTF_TABLE_NAME); + SWSS_LOG_INFO(" MCLAGSYNCD create cfg mclag intf table"); + + p_mclag_unique_ip_cfg_tbl = new SubscriberStateTable(p_config_db.get(), CFG_MCLAG_UNIQUE_IP_TABLE_NAME); + SWSS_LOG_INFO(" MCLAGSYNCD create cfg unique ip table"); + + if (p_state_fdb_tbl) + { + m_select->addSelectable(p_state_fdb_tbl); + SWSS_LOG_INFO(" MCLAGSYNCD Add state_fdb_tbl to selectable"); + } + + + if (p_state_vlan_mbr_subscriber_table) + { + m_select->addSelectable(p_state_vlan_mbr_subscriber_table); + SWSS_LOG_NOTICE(" MCLAGSYNCD Add p_state_vlan_mbr_subscriber_table to selectable"); + } + + //add mclag interface table to selectable + if (p_mclag_intf_cfg_tbl) + { + m_select->addSelectable(p_mclag_intf_cfg_tbl); + SWSS_LOG_NOTICE("MCLagSYNCD Adding mclag_intf_cfg_tbl to selectable"); + } + + //add mclag unique ip table to selectable + if (p_mclag_unique_ip_cfg_tbl) + { + m_select->addSelectable(getMclagUniqueCfgTable()); + SWSS_LOG_NOTICE("MCLagSYNCD Adding mclag_unique_ip_cfg_tbl to selectable"); + } +} + +void MclagLink::delDomainCfgDependentSelectables() +{ + if (p_mclag_intf_cfg_tbl) + { + m_select->removeSelectable(getMclagIntfCfgTable()); + SWSS_LOG_NOTICE("MCLagSYNCD remove mclag_intf_cfg_tbl to selectable"); + delete p_mclag_intf_cfg_tbl; + p_mclag_intf_cfg_tbl = NULL; + } + + if (p_mclag_unique_ip_cfg_tbl) + { + m_select->removeSelectable(getMclagUniqueCfgTable()); + SWSS_LOG_NOTICE("MCLagSYNCD remove mclag_unique_ip_cfg_tbl to selectable"); + delete p_mclag_unique_ip_cfg_tbl; + p_mclag_unique_ip_cfg_tbl = NULL; + } + + if (p_state_fdb_tbl) + { + m_select->removeSelectable(p_state_fdb_tbl); + SWSS_LOG_INFO(" MCLAGSYNCD remove state_fdb_tbl from selectable"); + delete p_state_fdb_tbl; + p_state_fdb_tbl = NULL; + } + + if (p_state_vlan_mbr_subscriber_table) + { + m_select->removeSelectable(p_state_vlan_mbr_subscriber_table); + SWSS_LOG_INFO(" MCLAGSYNCD remove p_state_vlan_mbr_subscriber_table selectable"); + + delete p_state_vlan_mbr_subscriber_table; + p_state_vlan_mbr_subscriber_table = NULL; + } +} + + +void MclagLink::mclagsyncdSendMclagIfaceCfg(std::deque &entries) +{ + struct mclag_iface_cfg_info cfg_info; + mclag_msg_hdr_t *cfg_msg_hdr = NULL; + size_t infor_len = sizeof(mclag_msg_hdr_t); + int count = 0; + vector po_names; + + ssize_t write = 0; + char *infor_start = getSendMsgBuffer(); + + /* Nothing popped */ + if (entries.empty()) + { + return; + } + + for (auto entry: entries) + { + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); + + std::size_t delimiter_pos = key.find_first_of("|"); + auto domain_id_str = key.substr(0, delimiter_pos); + std::string mclag_ifaces; + + memset(&cfg_info, 0, sizeof(mclag_iface_cfg_info)); + + count++; + SWSS_LOG_DEBUG("mclag iface cfg ; Key %s passed", key.c_str()); + + cfg_info.domain_id = stoi(domain_id_str); + + mclag_ifaces = key.substr(delimiter_pos+1); + if (mclag_ifaces.empty()) + { + SWSS_LOG_ERROR("Invalid Key %s Format. No mclag iface specified", key.c_str()); + continue; + } + + if(op == "SET") + { + cfg_info.op_type = MCLAG_CFG_OPER_ADD; + } + else + { + cfg_info.op_type = MCLAG_CFG_OPER_DEL; + + /* Delete local interface port isolation setting from STATE_DB */ + deleteLocalIfPortIsolate(mclag_ifaces); + } + + memcpy(cfg_info.mclag_iface, mclag_ifaces.c_str(), mclag_ifaces.size()); + po_names.push_back(mclag_ifaces); + + SWSS_LOG_DEBUG("domain_id:%d optype:%d mclag_ifaces:%s", cfg_info.domain_id, cfg_info.op_type, cfg_info.mclag_iface); + + if (MCLAG_MAX_SEND_MSG_LEN - infor_len < (sizeof(struct mclag_iface_cfg_info)) ) + { + cfg_msg_hdr = reinterpret_cast(static_cast(infor_start)); + cfg_msg_hdr->version = 1; + cfg_msg_hdr->msg_len = (unsigned short)infor_len; + cfg_msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE; + + SWSS_LOG_DEBUG("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d", + cfg_msg_hdr->msg_len, cfg_msg_hdr->msg_type, count); + write = ::write(getConnSocket(), infor_start, cfg_msg_hdr->msg_len); + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, mclag iface cfg send, buffer full; write to m_connection_socket failed"); + } + + infor_len = sizeof(mclag_msg_hdr_t); + } + memcpy((char*)(infor_start + infor_len), (char*)&cfg_info, sizeof(struct mclag_iface_cfg_info)); + infor_len += sizeof(struct mclag_iface_cfg_info) ; + } + + /*no config info notification reqd */ + if (infor_len <= sizeof(mclag_msg_hdr_t)) + return; + + cfg_msg_hdr = reinterpret_cast(static_cast(infor_start)); + cfg_msg_hdr->version = 1; + cfg_msg_hdr->msg_len = (unsigned short)infor_len; + cfg_msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_IFACE; + + SWSS_LOG_DEBUG("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d ver:%d ", cfg_msg_hdr->msg_len, cfg_msg_hdr->msg_type, cfg_msg_hdr->version, count); + write = ::write(getConnSocket(), infor_start, cfg_msg_hdr->msg_len); + + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, mclag iface cfg send; write to m_connection_socket failed"); + } + return; +} + +void MclagLink::mclagsyncdSendMclagUniqueIpCfg(std::deque &entries) +{ + struct mclag_unique_ip_cfg_info cfg_info; + mclag_msg_hdr_t *cfg_msg_hdr = NULL; + size_t infor_len = sizeof(mclag_msg_hdr_t); + int count = 0; + + ssize_t write = 0; + char *infor_start = getSendMsgBuffer(); + + /* Nothing popped */ + if (entries.empty()) + { + return; + } + + for (auto entry: entries) + { + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); + + std::size_t delimiter_pos = key.find_first_of("|"); + auto domain_id_str = key.substr(0, delimiter_pos); + std::string unique_ip_ifnames; + + memset(&cfg_info, 0, sizeof(mclag_unique_ip_cfg_info)); + + count++; + SWSS_LOG_NOTICE("mclag unique ip interface Key %s passed", key.c_str()); + + unique_ip_ifnames = key.substr(delimiter_pos+1); + if (unique_ip_ifnames.empty()) + { + SWSS_LOG_ERROR("Invalid Key %s Format. No unique ip ifname specified", key.c_str()); + continue; + } + + if(op == "SET") + { + cfg_info.op_type = MCLAG_CFG_OPER_ADD; + } + else + { + cfg_info.op_type = MCLAG_CFG_OPER_DEL; + } + + memcpy(cfg_info.mclag_unique_ip_ifname, unique_ip_ifnames.c_str(), unique_ip_ifnames.size()); + + SWSS_LOG_NOTICE("optype:%d mclag_unique_ip_ifname:%s", cfg_info.op_type, cfg_info.mclag_unique_ip_ifname); + + if (MCLAG_MAX_SEND_MSG_LEN - infor_len < (sizeof(struct mclag_unique_ip_cfg_info)) ) + { + cfg_msg_hdr = reinterpret_cast(static_cast(infor_start)); + cfg_msg_hdr->version = 1; + cfg_msg_hdr->msg_len = (unsigned short)infor_len; + cfg_msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP; + + SWSS_LOG_NOTICE("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d", + cfg_msg_hdr->msg_len, cfg_msg_hdr->msg_type, count); + + write = ::write(getConnSocket(), infor_start, cfg_msg_hdr->msg_len); + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, mclag unique ip cfg send, buffer full; write to m_connection_socket failed"); + } + + infor_len = sizeof(mclag_msg_hdr_t); + } + memcpy((char*)(infor_start + infor_len), (char*)&cfg_info, sizeof(struct mclag_unique_ip_cfg_info)); + infor_len += sizeof(struct mclag_unique_ip_cfg_info); + } + + /*no config info notification reqd */ + if (infor_len <= sizeof(mclag_msg_hdr_t)) + return; + + cfg_msg_hdr = reinterpret_cast(static_cast(infor_start)); + cfg_msg_hdr->version = 1; + cfg_msg_hdr->msg_len = (unsigned short)infor_len; + cfg_msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_CFG_MCLAG_UNIQUE_IP; + + SWSS_LOG_NOTICE("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d ver:%d ", + cfg_msg_hdr->msg_len, cfg_msg_hdr->msg_type, cfg_msg_hdr->version, count); + + write = ::write(getConnSocket(), infor_start, cfg_msg_hdr->msg_len); + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, mclag unique ip cfg send; write to m_connection_socket failed"); + } + + return; +} + +void MclagLink::processVlanMemberTableUpdates(std::deque &entries) +{ + struct mclag_vlan_mbr_info vlan_mbr_info; + mclag_msg_hdr_t *msg_hdr = NULL; + size_t infor_len = sizeof(mclag_msg_hdr_t); + int count = 0; + + ssize_t write = 0; + char *infor_start = getSendMsgBuffer(); + + /* Nothing popped */ + if (entries.empty()) + { + return; + } + + for (auto entry: entries) + { + std::string key = kfvKey(entry); + std::string op = kfvOp(entry); + int vlan_mbrship_found = 0; + + std::size_t delimiter_pos = key.find_first_of("|"); + std::string vlan_mbr_iface; + unsigned int vlan_id; + + auto vlan_id_str = key.substr(0, delimiter_pos); + vlan_id = (unsigned int) stoi(vlan_id_str.substr(4)); + vlan_mbr_iface = key.substr(delimiter_pos+1); + + memset(&vlan_mbr_info, 0, sizeof(vlan_mbr_info)); + + SWSS_LOG_DEBUG("%s: vlan_id:%d vlan_mbr:%s ", __FUNCTION__, vlan_id, vlan_mbr_iface.c_str()); + + vlan_mbrship_found = findVlanMbr(vlan_id_str.c_str(), vlan_mbr_iface.c_str()); + if(op == "SET") + { + vlan_mbr_info.op_type = MCLAG_CFG_OPER_ADD; + //found already no need to add and send again + if(vlan_mbrship_found) + { + continue; + } + addVlanMbr(vlan_id_str.c_str(), vlan_mbr_iface.c_str()); + } + else + { + //if member not found - skip delete + if(!vlan_mbrship_found) + { + SWSS_LOG_NOTICE("%s: duplicate vlan member delete; vlan_id:%d vlan_mbr:%s ", __FUNCTION__, vlan_id, vlan_mbr_iface.c_str()); + continue; + } + vlan_mbr_info.op_type = MCLAG_CFG_OPER_DEL; + delVlanMbr(vlan_id_str.c_str(), vlan_mbr_iface.c_str()); + } + + count++; + vlan_mbr_info.vid = vlan_id; + memcpy(vlan_mbr_info.mclag_iface, vlan_mbr_iface.c_str(), sizeof(vlan_mbr_info.mclag_iface)); + + + if (MCLAG_MAX_SEND_MSG_LEN - infor_len < (sizeof(struct mclag_vlan_mbr_info)) ) + { + msg_hdr = reinterpret_cast(static_cast(infor_start)); + msg_hdr->version = 1; + msg_hdr->msg_len = (unsigned short)infor_len; + msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES; + + SWSS_LOG_NOTICE("mclagsycnd send msg to iccpd, msg_len =%d, msg_type =%d count : %d", msg_hdr->msg_len, msg_hdr->msg_type, (count -1)); + write = ::write(getConnSocket(), infor_start, msg_hdr->msg_len); + + count = 0; + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, mclag vlan member updates send, buffer full; write to m_connection_socket failed"); + } + + infor_len = sizeof(mclag_msg_hdr_t); + } + memcpy((char*)(infor_start + infor_len), (char*)&vlan_mbr_info, sizeof(struct mclag_vlan_mbr_info)); + infor_len += sizeof(struct mclag_vlan_mbr_info) ; + } + + /*no config info notification reqd */ + if (infor_len <= sizeof(mclag_msg_hdr_t)) + return; + + msg_hdr = reinterpret_cast(static_cast(infor_start)); + msg_hdr->version = 1; + msg_hdr->msg_len = (unsigned short)infor_len; + msg_hdr->msg_type = MCLAG_SYNCD_MSG_TYPE_VLAN_MBR_UPDATES; + + SWSS_LOG_NOTICE("mclagsycnd send msg to iccpd,mclag vlan member updates; msg_len =%d, msg_type =%d count : %d ver:%d ", msg_hdr->msg_len, msg_hdr->msg_type, msg_hdr->version, count); + write = ::write(getConnSocket(), infor_start, msg_hdr->msg_len); + + + if (write <= 0) + { + SWSS_LOG_ERROR("mclagsycnd to ICCPD, mclag vlan member updates send; write to m_connection_socket failed"); + } + return; +} + + +/* Enable/Disable traffic distribution mode for LAG member port */ +void MclagLink::mclagsyncdSetTrafficDisable( + char *msg, + uint8_t msg_type) +{ + string lag_name; + string traffic_dist_disable; + mclag_sub_option_hdr_t *op_hdr = NULL; + vector fvVector; + + /* Get port-channel name */ + op_hdr = reinterpret_cast(static_cast(msg)); + if (op_hdr->op_type != MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME) + { + SWSS_LOG_ERROR("Invalid option type %u", op_hdr->op_type); + return; + } + lag_name.insert(0, (const char*)op_hdr->data, op_hdr->op_len); + + if (msg_type == MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE) + traffic_dist_disable = "true"; + else + traffic_dist_disable = "false"; + + fvVector.push_back(make_pair("traffic_disable", traffic_dist_disable)); + p_lag_tbl->set(lag_name, fvVector); + SWSS_LOG_NOTICE("Set traffic %s for %s", + (msg_type == MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE) ? + "disable" : "enable", lag_name.c_str()); +} + +/* Set the oper_status field in the STATE_MCLAG_TABLE */ +void MclagLink::mclagsyncdSetIccpState( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + bool is_oper_up = false; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + vector fvVector; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_OPER_STATUS: + memcpy(&is_oper_up, op_hdr->data, op_hdr->op_len); + fvVector.push_back( + make_pair("oper_status", is_oper_up ? "up" : "down")); + break; + + default: + SWSS_LOG_WARN("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((mlag_id > 0) && (fvVector.size() > 0)) + { + is_iccp_up = is_oper_up; + /* Update MLAG table: key = mlag_id, value = oper_status */ + p_mclag_tbl->set(to_string(mlag_id), fvVector); + SWSS_LOG_NOTICE("Set mlag %d ICCP state to %s", + mlag_id, is_oper_up ? "up" : "down"); + } + else + { + SWSS_LOG_ERROR("Invalid parameter, mlag %d", mlag_id); + } +} + +/* Set the role field in the STATE_MCLAG_TABLE */ +void MclagLink::mclagsyncdSetIccpRole( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + bool is_active_role; + bool valid_system_id = false; + string system_id_str; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + vector fvVector; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_ICCP_ROLE: + memcpy(&is_active_role, op_hdr->data, op_hdr->op_len); + fvVector.push_back( + make_pair("role", is_active_role ? "active" : "standby")); + break; + + case MCLAG_SUB_OPTION_TYPE_SYSTEM_ID: + valid_system_id = true; + system_id_str = MacAddress::to_string(op_hdr->data); + fvVector.push_back(make_pair("system_mac", system_id_str)); + break; + default: + SWSS_LOG_ERROR("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((mlag_id > 0) && (fvVector.size() > 0)) + { + /* Update MLAG table: key = mlag_id, value = role */ + p_mclag_tbl->set(to_string(mlag_id), fvVector); + SWSS_LOG_NOTICE("Set mlag %d ICCP role to %s, system_id(%s)", + mlag_id, is_active_role ? "active" : "standby", + valid_system_id ? system_id_str.c_str() : "None"); + } + else + { + SWSS_LOG_ERROR("Invalid parameter, mlag %d", mlag_id); + } +} + +/* Set the system_mac field in the STATE_MCLAG_TABLE */ +void MclagLink::mclagsyncdSetSystemId( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + string system_id_str; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + vector fvVector; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_SYSTEM_ID: + system_id_str = MacAddress::to_string(op_hdr->data); + fvVector.push_back(make_pair("system_mac", system_id_str)); + break; + + default: + SWSS_LOG_ERROR("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((mlag_id > 0) && (fvVector.size() > 0)) + { + /* Update MLAG table: key = mlag_id, value = system_mac */ + p_mclag_tbl->set(to_string(mlag_id), fvVector); + SWSS_LOG_NOTICE("Set mlag %d system mac to %s", + mlag_id, system_id_str.c_str()); + } + else + { + SWSS_LOG_ERROR("Invalid parameter, mlag %d", mlag_id); + } +} + +void MclagLink::processStateFdb(SubscriberStateTable *stateFdbTbl) +{ + SWSS_LOG_INFO("MCLAGSYNCD: Process State Fdb events "); + std::deque entries; + stateFdbTbl->pops(entries); + mclagsyncdSendFdbEntries(entries); +} + +void MclagLink::processStateVlanMember(SubscriberStateTable *stateVlanMemberTbl) +{ + SWSS_LOG_INFO("MCLAGSYNCD: Process State Vlan Member events "); + std::deque entries; + stateVlanMemberTbl->pops(entries); + processVlanMemberTableUpdates(entries); +} + +/* Delete Mlag entry in the STATE_MCLAG_TABLE */ +void MclagLink::mclagsyncdDelIccpInfo( + char *msg) +{ + int mlag_id; + mclag_sub_option_hdr_t *op_hdr = NULL; + vector fvVector; + + /* Get MLAG ID */ + op_hdr = reinterpret_cast(static_cast(msg)); + if (op_hdr->op_type != MCLAG_SUB_OPTION_TYPE_MCLAG_ID) + { + SWSS_LOG_ERROR("Invalid option type %u", op_hdr->op_type); + } + else + { + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + p_mclag_tbl->del(to_string(mlag_id)); + SWSS_LOG_NOTICE("Delete mlag %d", mlag_id); + } +} + +/* Set local interface portisolate field enable/disable in the + * STATE_MCLAG_LOCAL_INTF_TABLE. + * Key = "interface" + */ +void MclagLink::setLocalIfPortIsolate(std::string mclag_if, bool is_enable) +{ + vector fvVector; + std::string key; + + /* Update MLAG Local Interface table: key = interface, value = * enable/disable */ + key = mclag_if; + fvVector.push_back(make_pair("port_isolate_peer_link", is_enable ? "true" : "false")); + p_mclag_local_intf_tbl->set(key, fvVector); + SWSS_LOG_NOTICE("Set local interface %s to %s", mclag_if.c_str(), is_enable ? "true" : "false"); +} + +/* Delete local interface + * STATE_MCLAG_LOCAL_INTF_TABLE. + * Key = "interface" + */ +void MclagLink::deleteLocalIfPortIsolate(std::string mclag_if) +{ + vector fvVector; + std::string key; + + p_mclag_local_intf_tbl->del(mclag_if); + SWSS_LOG_NOTICE("Delete local interface %s", mclag_if.c_str()); +} + +/* Set remote interface state field oper_status in the + * STATE_MCLAG_REMOTE_INTF_TABLE. + * Key = "Mclag|interface" + */ +void MclagLink::mclagsyncdSetRemoteIfState( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + bool is_oper_up; + string lag_name; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + string key; + vector fvVector; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME: + lag_name.insert(0, (const char*)op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_OPER_STATUS: + memcpy(&is_oper_up, op_hdr->data, op_hdr->op_len); + fvVector.push_back( + make_pair("oper_status", is_oper_up ? "up" : "down")); + break; + + default: + SWSS_LOG_WARN("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((mlag_id > 0) && (!lag_name.empty()) && (fvVector.size() > 0)) + { + /* Update MLAG table: key = mclag|interface, value = oper_status */ + key = to_string(mlag_id) + "|" + lag_name; + p_mclag_remote_intf_tbl->set(key, fvVector); + SWSS_LOG_NOTICE("Set mlag %d, remote interface %s to %s", + mlag_id, lag_name.c_str(), is_oper_up ? "up" : "down"); + } + else + { + SWSS_LOG_ERROR("Invalid parameter, mlag %d, remote interface %s", + mlag_id, lag_name.empty() ? "None" : lag_name.c_str()); + } +} + +/* Delete remote interface state entry in the STATE_MCLAG_REMOTE_INTF_TABLE + * Key = "Mclag|interface" + */ +void MclagLink::mclagsyncdDelRemoteIfInfo( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + string lag_name; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + string key; + vector fvVector; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME: + lag_name.insert(0, (const char*)op_hdr->data, op_hdr->op_len); + break; + + default: + SWSS_LOG_WARN("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((mlag_id > 0) && (!lag_name.empty())) + { + key = to_string(mlag_id) + "|" + lag_name; + p_mclag_remote_intf_tbl->del(key); + SWSS_LOG_NOTICE("Delete mlag %d, remote interface %s", + mlag_id, lag_name.c_str()); + } + else + { + SWSS_LOG_ERROR("Invalid parameter, mlag %d", mlag_id); + } +} + +/* Set peer-link isolation for the specified Mlag interface + * Notes: Mlag-ID is not used currently for the local interface table + */ +void MclagLink::mclagsyncdSetPeerLinkIsolation( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + bool is_isolation_enable; + bool rx_isolation_setting = false; + string mclag_if_name; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_MCLAG_INTF_NAME: + mclag_if_name.insert(0, (const char*)op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_ISOLATION_STATE: + memcpy(&is_isolation_enable, op_hdr->data, op_hdr->op_len); + rx_isolation_setting = true; + break; + + default: + SWSS_LOG_WARN("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((!mclag_if_name.empty()) && rx_isolation_setting) + { + setLocalIfPortIsolate(mclag_if_name, is_isolation_enable); + SWSS_LOG_NOTICE("%s %s isolation from peer-link", + is_isolation_enable ? "Enable" : "Disable", mclag_if_name.c_str()); + } + else + { + SWSS_LOG_ERROR("Missing parameter, mclag interface %s, ", + mclag_if_name.empty() ? "None" : mclag_if_name.c_str()); + } +} + +/* Set the remote system mac field in the STATE_MCLAG_TABLE */ +void MclagLink::mclagsyncdSetPeerSystemId( + char *msg, + size_t msg_len) +{ + int mlag_id = 0; + string system_id_str; + char *cur; + size_t cur_len = 0; + mclag_sub_option_hdr_t *op_hdr; + vector fvVector; + + while (cur_len < msg_len) + { + cur = msg + cur_len; + op_hdr = reinterpret_cast(static_cast(cur)); + + switch(op_hdr->op_type) + { + case MCLAG_SUB_OPTION_TYPE_MCLAG_ID: + memcpy(&mlag_id, op_hdr->data, op_hdr->op_len); + break; + + case MCLAG_SUB_OPTION_TYPE_PEER_SYSTEM_ID: + system_id_str = MacAddress::to_string(op_hdr->data); + fvVector.push_back(make_pair("peer_mac", system_id_str)); + break; + + default: + SWSS_LOG_ERROR("Invalid option type %u", op_hdr->op_type); + break; + } + cur_len += (MCLAG_SUB_OPTION_HDR_LEN + op_hdr->op_len); + } + if ((mlag_id > 0) && (fvVector.size() > 0)) + { + /* Update MLAG table: key = mlag_id, value = system_mac */ + p_mclag_tbl->set(to_string(mlag_id), fvVector); + SWSS_LOG_NOTICE("Set mlag %d peer system mac to %s", mlag_id, system_id_str.c_str()); + } + else + { + SWSS_LOG_ERROR("Invalid parameter, mlag %d", mlag_id); + } +} + +MclagLink::MclagLink(Select *select, int port) : + MSG_BATCH_SIZE(256), + m_bufSize(MCLAG_MAX_MSG_LEN * MSG_BATCH_SIZE), + m_messageBuffer(NULL), + m_pos(0), + m_connected(false), + m_server_up(false), + m_select(select) +{ + struct sockaddr_in addr; + int true_val = 1; + + m_server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (m_server_socket < 0) + throw system_error(errno, system_category()); + + if (setsockopt(m_server_socket, SOL_SOCKET, SO_REUSEADDR, &true_val, + sizeof(true_val)) < 0) + { + close(m_server_socket); + throw system_error(errno, system_category()); + } + + if (setsockopt(m_server_socket, SOL_SOCKET, SO_KEEPALIVE, &true_val, + sizeof(true_val)) < 0) + { + close(m_server_socket); + throw system_error(errno, system_category()); + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons((unsigned short int)port); + addr.sin_addr.s_addr = htonl(MCLAG_DEFAULT_IP); + + if (bind(m_server_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + close(m_server_socket); + throw system_error(errno, system_category()); + } + + if (listen(m_server_socket, 2) != 0) + { + close(m_server_socket); + throw system_error(errno, system_category()); + } + + m_server_up = true; + m_messageBuffer = new char[m_bufSize]; + m_messageBuffer_send = new char[MCLAG_MAX_SEND_MSG_LEN]; + + p_learn = NULL; + + p_state_db = unique_ptr(new DBConnector("STATE_DB", 0)); + p_appl_db = unique_ptr(new DBConnector("APPL_DB", 0)); + p_config_db = unique_ptr(new DBConnector("CONFIG_DB", 0)); + p_asic_db = unique_ptr(new DBConnector("ASIC_DB", 0)); + p_counters_db = unique_ptr(new DBConnector("COUNTERS_DB", 0)); + p_notificationsDb = unique_ptr(new DBConnector("STATE_DB", 0)); + + p_device_metadata_tbl = unique_ptr(new Table(p_config_db.get(), CFG_DEVICE_METADATA_TABLE_NAME)); + p_mclag_cfg_table = unique_ptr
(new Table(p_config_db.get(), CFG_MCLAG_TABLE_NAME)); + p_mclag_intf_cfg_table = unique_ptr
(new Table(p_config_db.get(), CFG_MCLAG_INTF_TABLE_NAME)); + + p_mclag_tbl = unique_ptr
(new Table(p_state_db.get(), STATE_MCLAG_TABLE_NAME)); + p_mclag_local_intf_tbl = unique_ptr
(new Table(p_state_db.get(), STATE_MCLAG_LOCAL_INTF_TABLE_NAME)); + p_mclag_remote_intf_tbl = unique_ptr
(new Table(p_state_db.get(), STATE_MCLAG_REMOTE_INTF_TABLE_NAME)); + + + p_intf_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_INTF_TABLE_NAME)); + p_iso_grp_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_ISOLATION_GROUP_TABLE_NAME)); + p_fdb_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_MCLAG_FDB_TABLE_NAME)); + p_acl_table_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_ACL_TABLE_TABLE_NAME)); + p_acl_rule_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_ACL_RULE_TABLE_NAME)); + p_lag_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_LAG_TABLE_NAME)); + p_port_tbl = unique_ptr(new ProducerStateTable(p_appl_db.get(), APP_PORT_TABLE_NAME)); + + p_state_fdb_tbl = NULL; + p_state_vlan_mbr_subscriber_table = NULL; + p_mclag_intf_cfg_tbl = NULL; + p_mclag_unique_ip_cfg_tbl = NULL; +} + +MclagLink::~MclagLink() +{ + delete[] m_messageBuffer; + delete[] m_messageBuffer_send; + if (m_connected) + close(m_connection_socket); + if (m_server_up) + close(m_server_socket); + + if (p_state_fdb_tbl) + delete p_state_fdb_tbl; + + if (p_state_vlan_mbr_subscriber_table) + delete p_state_vlan_mbr_subscriber_table; + + if (p_mclag_unique_ip_cfg_tbl) + delete p_mclag_unique_ip_cfg_tbl; + + if (p_mclag_intf_cfg_tbl) + delete p_mclag_intf_cfg_tbl; +} + +void MclagLink::accept() +{ + struct sockaddr_in client_addr; + socklen_t client_len; + + m_connection_socket = ::accept(m_server_socket, (struct sockaddr *)&client_addr, + &client_len); + if (m_connection_socket < 0) + throw system_error(errno, system_category()); + + SWSS_LOG_NOTICE("New connection accepted from: %s", inet_ntoa(client_addr.sin_addr)); +} + +int MclagLink::getFd() +{ + return m_connection_socket; +} + +char* MclagLink::getSendMsgBuffer() +{ + return m_messageBuffer_send; +} + +int MclagLink::getConnSocket() +{ + return m_connection_socket; +} + + +uint64_t MclagLink::readData() +{ + mclag_msg_hdr_t *hdr = NULL; + size_t msg_len = 0; + size_t start = 0, left = 0; + ssize_t read = 0; + char * msg = NULL; + + read = ::read(m_connection_socket, m_messageBuffer + m_pos, m_bufSize - m_pos); + if (read == 0) + throw MclagConnectionClosedException(); + if (read < 0) + throw system_error(errno, system_category()); + m_pos += (uint32_t)read; while (true) { @@ -697,10 +1909,6 @@ uint64_t MclagLink::readData() setFdbFlush(); break; - case MCLAG_MSG_TYPE_FLUSH_FDB_BY_PORT: - setFdbFlushByPort(msg); - break; - case MCLAG_MSG_TYPE_SET_INTF_MAC: setIntfMac(msg); break; @@ -708,25 +1916,41 @@ uint64_t MclagLink::readData() case MCLAG_MSG_TYPE_SET_FDB: setFdbEntry(msg, (int)(hdr->msg_len - sizeof(mclag_msg_hdr_t))); break; - - case MCLAG_MSG_TYPE_GET_FDB_CHANGES: - write = getFdbChange(m_messageBuffer_send); - if (write == 0) - throw MclagConnectionClosedException(); - if (write < 0) - throw system_error(errno, system_category()); + case MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_ENABLE: + case MCLAG_MSG_TYPE_SET_TRAFFIC_DIST_DISABLE: + mclagsyncdSetTrafficDisable(msg, hdr->msg_type); + break; + case MCLAG_MSG_TYPE_SET_ICCP_STATE: + mclagsyncdSetIccpState(msg, mclag_msg_data_len(hdr)); + break; + case MCLAG_MSG_TYPE_SET_ICCP_ROLE: + mclagsyncdSetIccpRole(msg, mclag_msg_data_len(hdr)); + break; + case MCLAG_MSG_TYPE_SET_ICCP_SYSTEM_ID: + mclagsyncdSetSystemId(msg, mclag_msg_data_len(hdr)); + break; + case MCLAG_MSG_TYPE_DEL_ICCP_INFO: + mclagsyncdDelIccpInfo(msg); + break; + case MCLAG_MSG_TYPE_SET_REMOTE_IF_STATE: + mclagsyncdSetRemoteIfState(msg, mclag_msg_data_len(hdr)); + break; + case MCLAG_MSG_TYPE_DEL_REMOTE_IF_INFO: + mclagsyncdDelRemoteIfInfo(msg, mclag_msg_data_len(hdr)); + break; + case MCLAG_MSG_TYPE_SET_PEER_LINK_ISOLATION: + mclagsyncdSetPeerLinkIsolation(msg, mclag_msg_data_len(hdr)); + break; + case MCLAG_MSG_TYPE_SET_ICCP_PEER_SYSTEM_ID: + mclagsyncdSetPeerSystemId(msg, mclag_msg_data_len(hdr)); break; - default: break; } start += msg_len; } - memmove(m_messageBuffer, m_messageBuffer + start, m_pos - start); m_pos = m_pos - (uint32_t)start; - return 0; } - diff --git a/mclagsyncd/mclaglink.h b/mclagsyncd/mclaglink.h index 4a4e74dcdb..9c23c97686 100644 --- a/mclagsyncd/mclaglink.h +++ b/mclagsyncd/mclaglink.h @@ -33,119 +33,303 @@ #include #include #include +#include +#include #include "producerstatetable.h" +#include "subscriberstatetable.h" +#include "select.h" #include "selectable.h" #include "mclagsyncd/mclag.h" +#include "notificationconsumer.h" +#include "notificationproducer.h" -namespace swss { -#define ETHER_ADDR_STR_LEN 18 +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif /* INET_ADDRSTRLEN */ + #define MAX_L_PORT_NAME 20 +#define BRCM_PLATFORM_SUBSTRING "broadcom" + +using namespace std; + +namespace swss { + + struct mclag_fdb_info + { + uint8_t mac[ETHER_ADDR_LEN]; + unsigned int vid; + char port_name[MAX_L_PORT_NAME]; + short type;/*dynamic or static*/ + short op_type;/*add or del*/ + }; + + struct mclag_domain_cfg_info + { + int op_type;/*add/del domain; add/del mclag domain */ + int domain_id; + int keepalive_time; + int session_timeout; + char local_ip[INET_ADDRSTRLEN]; + char peer_ip[INET_ADDRSTRLEN]; + char peer_ifname[MAX_L_PORT_NAME]; + uint8_t system_mac[ETHER_ADDR_LEN]; + int attr_bmap; + }; -struct mclag_fdb_info -{ - char mac[ETHER_ADDR_STR_LEN]; - unsigned int vid; - char port_name[MAX_L_PORT_NAME]; - short type; /*dynamic or static*/ - short op_type; /*add or del*/ -}; - -struct mclag_fdb -{ - std::string mac; - unsigned int vid; - std::string port_name; - std::string type;/*dynamic or static*/ - - mclag_fdb(std::string val_mac, unsigned int val_vid, std::string val_pname, - std::string val_type) : mac(val_mac), vid(val_vid), port_name(val_pname), type(val_type) + struct mclag_iface_cfg_info { - } - mclag_fdb() + int op_type;/*add/del domain; add/del mclag iface */ + int domain_id; + char mclag_iface[MAX_L_PORT_NAME]; + }; + + struct mclag_unique_ip_cfg_info { - } + int op_type;/*add/del mclag unique ip iface */ + char mclag_unique_ip_ifname[MAX_L_PORT_NAME]; + }; + + struct mclag_vlan_mbr_info + { + int op_type;/*add/del vlan_member */ + unsigned int vid; + char mclag_iface[MAX_L_PORT_NAME]; + }; + - bool operator <(const mclag_fdb &fdb) const + struct mclag_fdb { - if (mac != fdb.mac) - return mac < fdb.mac; - else if (vid != fdb.vid) - return vid < fdb.vid; - else - return port_name < fdb.port_name; - //else if (port_name != fdb.port_name) return port_name < fdb.port_name; - //else return type *p_old_fdb; - - MclagLink(uint16_t port = MCLAG_DEFAULT_PORT); - virtual ~MclagLink(); - - /* Wait for connection (blocking) */ - void accept(); - - int getFd() override; - uint64_t readData() override; - - /* readMe throws MclagConnectionClosedException when connection is lost */ - class MclagConnectionClosedException : public std::exception + unsigned int domain_id; + + mclagDomainEntry() {} + mclagDomainEntry(unsigned int id):domain_id(id) {} + + bool operator <(const mclagDomainEntry &domain) const + { + return domain_id < domain.domain_id; + } + + bool operator ==(const mclagDomainEntry &domain) const + { + return (domain_id == domain.domain_id); + } + }; + + + //MCLAG Domain Data + struct mclagDomainData { + std::string source_ip; + std::string peer_ip; + std::string peer_link; + int keepalive_interval; + int session_timeout; + + mclagDomainData() + { + keepalive_interval = -1; + session_timeout = -1; + } + + bool mandatoryFieldsPresent() const + { + return (!source_ip.empty() && !peer_ip.empty()); + } + + bool allFieldsEmpty() const + { + return (source_ip.empty() && peer_ip.empty() && peer_link.empty() && keepalive_interval == -1 && session_timeout == -1); + } }; -private: - unsigned int m_bufSize; - char *m_messageBuffer; - char *m_messageBuffer_send; - unsigned int m_pos; - - bool m_connected; - bool m_server_up; - int m_server_socket; - int m_connection_socket; - - void getOidToPortNameMap(std::unordered_map & port_map); - void getBridgePortIdToAttrPortIdMap(std::map *oid_map); - void getVidByBvid(std::string &bvid, std::string &vlanid); - void getFdbSet(std::set *fdb_set); - void setPortIsolate(char *msg); - void setPortMacLearnMode(char *msg); - void setFdbFlush(); - void setFdbFlushByPort(char *msg); - void setIntfMac(char *msg); - void setFdbEntry(char *msg, int msg_len); - ssize_t getFdbChange(char *msg_buf); - void connectionLostHandlePortIsolate(); - void connectionLostHandlePortLearnMode(); - void connectionLost(); -}; + typedef std::tuple vlan_mbr; + + class MclagLink : public Selectable { + + private: + Select *m_select; + unsigned int m_bufSize; + char *m_messageBuffer; + char *m_messageBuffer_send; + unsigned int m_pos; + + bool m_connected; + bool m_server_up; + int m_server_socket; + int m_connection_socket; + + bool is_iccp_up = false; + std::string m_system_mac; + std::set m_vlan_mbrship; //set of vlan,mbr tuples + + const int MSG_BATCH_SIZE; + std::map *p_learn; + + unique_ptr p_state_db; + unique_ptr p_appl_db; + unique_ptr p_config_db; + unique_ptr p_asic_db; + unique_ptr p_counters_db; + unique_ptr p_notificationsDb; + + unique_ptr
p_mclag_tbl; + unique_ptr
p_mclag_local_intf_tbl; + unique_ptr
p_mclag_remote_intf_tbl; + unique_ptr
p_device_metadata_tbl; + unique_ptr
p_mclag_cfg_table; + unique_ptr
p_mclag_intf_cfg_table; + + unique_ptr p_port_tbl; + unique_ptr p_intf_tbl; + unique_ptr p_acl_table_tbl; + unique_ptr p_acl_rule_tbl; + unique_ptr p_lag_tbl; + unique_ptr p_iso_grp_tbl; + unique_ptr p_fdb_tbl; + + SubscriberStateTable *p_mclag_intf_cfg_tbl; + SubscriberStateTable *p_mclag_unique_ip_cfg_tbl; + + SubscriberStateTable *p_state_fdb_tbl; + SubscriberStateTable *p_state_vlan_mbr_subscriber_table; + + std::map m_mclag_domains; + + + int getFd() override; + char* getSendMsgBuffer(); + int getConnSocket(); + uint64_t readData() override; + + void mclagsyncdSendFdbEntries(std::deque &entries); + + + void mclagsyncdSetTrafficDisable(char *msg_buf, uint8_t msg_type); + void mclagsyncdSetIccpState(char *msg, size_t msg_size); + void mclagsyncdSetIccpRole(char *msg, size_t msg_size); + void mclagsyncdSetSystemId(char *msg, size_t msg_size); + void mclagsyncdDelIccpInfo(char *msg); + void mclagsyncdSetRemoteIfState(char *msg, size_t msg_size); + void mclagsyncdDelRemoteIfInfo(char *msg, size_t msg_size); + void mclagsyncdSetPeerLinkIsolation(char *msg, size_t msg_size); + void mclagsyncdSetPeerSystemId(char *msg, size_t msg_size); + + + void addDomainCfgDependentSelectables(); + + void delDomainCfgDependentSelectables(); + + void getOidToPortNameMap(std::unordered_map & port_map); + void getBridgePortIdToAttrPortIdMap(std::map *oid_map); + void getVidByBvid(std::string &bvid, std::string &vlanid); + void getFdbSet(std::set *fdb_set); + void setLocalIfPortIsolate(std::string mclag_if, bool is_enable); + void deleteLocalIfPortIsolate(std::string mclag_if); + void setPortIsolate(char *msg); + void setPortMacLearnMode(char *msg); + void setPortMacLearnNLAPI(char *msg); + void setFdbFlush(); + void setIntfMac(char *msg); + void setFdbEntry(char *msg, int msg_len); + + void addVlanMbr(std::string, std::string); + void delVlanMbr(std::string, std::string); + int findVlanMbr(std::string, std::string); + + + + public: + MclagLink(Select* select, int port = MCLAG_DEFAULT_PORT); + + virtual ~MclagLink(); + + /* readMe throws MclagConnectionClosedException when connection is lost */ + class MclagConnectionClosedException : public std::exception + { + }; + + /* Wait for connection (blocking) */ + void accept(); + + void mclagsyncdFetchSystemMacFromConfigdb(); + void mclagsyncdFetchMclagConfigFromConfigdb(); + void mclagsyncdFetchMclagInterfaceConfigFromConfigdb(); + + SubscriberStateTable *getStateFdbTable() + { + return p_state_fdb_tbl; + } + + SubscriberStateTable *getStateVlanMemberTable() + { + return p_state_vlan_mbr_subscriber_table; + } + + SubscriberStateTable *getMclagIntfCfgTable() + { + return p_mclag_intf_cfg_tbl; + } + + SubscriberStateTable *getMclagUniqueCfgTable() + { + return p_mclag_unique_ip_cfg_tbl; + } + + + void processMclagDomainCfg(std::deque &entries); + void processVlanMemberTableUpdates(std::deque &entries); + + void processStateFdb(SubscriberStateTable *stateFdbTbl); + void processStateVlanMember(SubscriberStateTable *stateVlanMemberTbl); + + void mclagsyncdSendMclagIfaceCfg(std::deque &entries); + void mclagsyncdSendMclagUniqueIpCfg(std::deque &entries); + + }; } #endif + diff --git a/mclagsyncd/mclagsyncd.cpp b/mclagsyncd/mclagsyncd.cpp index 39221d345d..bbd48a7e50 100644 --- a/mclagsyncd/mclagsyncd.cpp +++ b/mclagsyncd/mclagsyncd.cpp @@ -21,8 +21,10 @@ #include "logger.h" #include #include "select.h" +#include "logger.h" #include "netdispatcher.h" #include "mclagsyncd/mclaglink.h" +#include "schema.h" #include using namespace std; @@ -31,53 +33,80 @@ using namespace swss; int main(int argc, char **argv) { swss::Logger::linkToDbNative("mclagsyncd"); + DBConnector appl_db("APPL_DB", 0); - DBConnector asic_db("ASIC_DB", 0); - DBConnector counters_db("COUNTERS_DB", 0); - ProducerStateTable port_tbl(&appl_db, APP_PORT_TABLE_NAME); - ProducerStateTable lag_tbl(&appl_db, APP_LAG_TABLE_NAME); - ProducerStateTable tnl_tbl(&appl_db, APP_VXLAN_TUNNEL_TABLE_NAME); - ProducerStateTable intf_tbl(&appl_db, APP_INTF_TABLE_NAME); - ProducerStateTable fdb_tbl(&appl_db, APP_FDB_TABLE_NAME); - ProducerStateTable acl_table_tbl(&appl_db, APP_ACL_TABLE_TABLE_NAME); - ProducerStateTable acl_rule_tbl(&appl_db, APP_ACL_RULE_TABLE_NAME); - map isolate; RedisPipeline pipeline(&appl_db); - set old_fdb; + DBConnector config_db("CONFIG_DB", 0); + SubscriberStateTable mclag_cfg_tbl(&config_db, CFG_MCLAG_TABLE_NAME); + + map learn_mode; while (1) { try { - MclagLink mclag; Select s; + MclagLink mclag(&s); - mclag.p_port_tbl = &port_tbl; - mclag.p_lag_tbl = &lag_tbl; - mclag.p_tnl_tbl = &tnl_tbl; - mclag.p_intf_tbl = &intf_tbl; - mclag.p_fdb_tbl = &fdb_tbl; - mclag.p_acl_table_tbl = &acl_table_tbl; - mclag.p_acl_rule_tbl = &acl_rule_tbl; - mclag.p_appl_db = &appl_db; - mclag.p_asic_db = &asic_db; - mclag.p_counters_db = &counters_db; - mclag.p_old_fdb = &old_fdb; + mclag.mclagsyncdFetchSystemMacFromConfigdb(); cout << "Waiting for connection..." << endl; mclag.accept(); cout << "Connected!" << endl; + mclag.mclagsyncdFetchMclagConfigFromConfigdb(); + mclag.mclagsyncdFetchMclagInterfaceConfigFromConfigdb(); + s.addSelectable(&mclag); + //add mclag domain config table to selectable + s.addSelectable(&mclag_cfg_tbl); + SWSS_LOG_NOTICE("MCLagSYNCD Adding mclag_cfg_tbl to selectables"); + while (true) { Selectable *temps; /* Reading MCLAG messages forever (and calling "readData" to read them) */ s.select(&temps); - pipeline.flush(); - SWSS_LOG_DEBUG("Pipeline flushed"); + + + if(temps == (Selectable *)mclag.getStateFdbTable()) + { + SWSS_LOG_INFO(" MCLAGSYNCD Matching state_fdb_tbl selectable"); + mclag.processStateFdb((SubscriberStateTable *)temps); + } + else if ( temps == (Selectable *)&mclag_cfg_tbl ) //Reading MCLAG Domain Config Table + { + SWSS_LOG_DEBUG("MCLAGSYNCD processing mclag_cfg_tbl notifications"); + std::deque entries; + mclag_cfg_tbl.pops(entries); + mclag.processMclagDomainCfg(entries); + } + else if ( temps == (Selectable *)mclag.getMclagIntfCfgTable() ) //Reading MCLAG Interface Config Table + { + SWSS_LOG_DEBUG("MCLAGSYNCD processing mclag_intf_cfg_tbl notifications"); + std::deque entries; + mclag.getMclagIntfCfgTable()->pops(entries); + mclag.mclagsyncdSendMclagIfaceCfg(entries); + } + else if (temps == (Selectable *)mclag.getMclagUniqueCfgTable()) //Reading MCLAG Unique IP Config Table + { + SWSS_LOG_DEBUG("MCLAGSYNCD processing mclag_unique_ip_cfg_tbl notifications"); + std::deque entries; + mclag.getMclagUniqueCfgTable()->pops(entries); + mclag.mclagsyncdSendMclagUniqueIpCfg(entries); + } + else if (temps == (Selectable *)mclag.getStateVlanMemberTable()) + { + SWSS_LOG_INFO(" MCLAGSYNCD Matching vlan Member selectable"); + mclag.processStateVlanMember((SubscriberStateTable *)temps); + } + else + { + pipeline.flush(); + SWSS_LOG_DEBUG("Pipeline flushed"); + } } } catch (MclagLink::MclagConnectionClosedException &e) @@ -94,3 +123,4 @@ int main(int argc, char **argv) return 1; } +