diff --git a/cfgmgr/natmgr.cpp b/cfgmgr/natmgr.cpp index 5df7a750841d..894496122edb 100644 --- a/cfgmgr/natmgr.cpp +++ b/cfgmgr/natmgr.cpp @@ -42,7 +42,8 @@ NatMgr::NatMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, con m_appTwiceNatTableProducer(appDb, APP_NAT_TWICE_TABLE_NAME), m_appTwiceNaptTableProducer(appDb, APP_NAPT_TWICE_TABLE_NAME), m_appNatGlobalTableProducer(appDb, APP_NAT_GLOBAL_TABLE_NAME), - m_appNaptPoolIpTable(appDb, APP_NAPT_POOL_IP_TABLE_NAME) + m_appNaptPoolIpTable(appDb, APP_NAPT_POOL_IP_TABLE_NAME), + m_appNatDnatPoolProducer(appDb, APP_NAT_DNAT_POOL_TABLE_NAME) { SWSS_LOG_ENTER(); @@ -71,7 +72,7 @@ NatMgr::NatMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, con flushNotifier = std::make_shared(appDb, "FLUSHNATREQUEST"); } -/* To check the port init id done or not */ +/* To check the port init is done or not */ bool NatMgr::isPortInitDone(DBConnector *app_db) { bool portInit = 0; @@ -676,6 +677,12 @@ bool NatMgr::setMangleIptablesRules(const string &opCmd, const string &interface std::string res; int ret; + if (nat_zone.empty()) + { + SWSS_LOG_INFO("Nat zone is empty"); + return false; + } + const std::string cmds = std::string("") + IPTABLES_CMD + " -t mangle " + "-" + opCmd + " PREROUTING -i " + interface + " -j MARK --set-mark " + nat_zone + " && " + IPTABLES_CMD + " -t mangle " + "-" + opCmd + " POSTROUTING -o " + interface + " -j MARK --set-mark " + nat_zone ; @@ -1110,7 +1117,7 @@ bool NatMgr::setDynamicNatIptablesRulesWithAcl(const string &opCmd, const string + IPTABLES_CMD + " -t nat " + "-" + opCmd + " POSTROUTING -p udp" + srcIpAddressString + dstIpAddressString + srcPortString + dstPortString + " -j RETURN" + " && " + IPTABLES_CMD + " -t nat " + "-" + opCmd + " POSTROUTING -p icmp" + srcIpAddressString + dstIpAddressString - + srcPortString + dstPortString + " -j RETURN"; + + " -j RETURN"; } else { @@ -1123,7 +1130,7 @@ bool NatMgr::setDynamicNatIptablesRulesWithAcl(const string &opCmd, const string + IPTABLES_CMD + " -t nat " + "-" + opCmd + " POSTROUTING -p udp" + srcIpAddressString + " -d " + keys[0] + srcPortString + " --dport " + keys[2] + " -j RETURN" + " && " + IPTABLES_CMD + " -t nat " + "-" + opCmd + " POSTROUTING -p icmp" + srcIpAddressString + " -d " + keys[0] - + srcPortString + " --dport " + keys[2] + " -j RETURN"; + + " -j RETURN"; } else { @@ -1133,7 +1140,7 @@ bool NatMgr::setDynamicNatIptablesRulesWithAcl(const string &opCmd, const string + IPTABLES_CMD + " -t nat " + "-" + opCmd + " POSTROUTING -p udp" + srcIpAddressString + " -d " + keys[0] + srcPortString + " -j RETURN" + " && " + IPTABLES_CMD + " -t nat " + "-" + opCmd + " POSTROUTING -p icmp" + srcIpAddressString + " -d " + keys[0] - + srcPortString + " -j RETURN"; + + " -j RETURN"; } } @@ -1226,6 +1233,92 @@ bool NatMgr::setDynamicNatIptablesRulesWithAcl(const string &opCmd, const string return true; } +/* To add/remove a DNAT Pool entry from Nat Pool */ +void NatMgr::setDnatPoolfromNatPool(const string &opCmd, const string &ip_range) +{ + uint32_t ipv4_addr_low, ipv4_addr_high, ip; + vector nat_ip = tokenize(ip_range, range_specifier); + + /* Check the pool is valid */ + if (nat_ip.empty()) + { + SWSS_LOG_INFO("NAT pool is not valid"); + return; + } + else if (nat_ip.size() == 2) + { + IpAddress addr_high(nat_ip[1]); + ipv4_addr_high = ntohl(addr_high.getV4Addr()); + IpAddress addr_low(nat_ip[0]); + ipv4_addr_low = ntohl(addr_low.getV4Addr()); + } + else + { + IpAddress addr_high(nat_ip[0]); + ipv4_addr_high = ntohl(addr_high.getV4Addr()); + ipv4_addr_low = ipv4_addr_high; + } + + for (ip = ipv4_addr_low; ip <= ipv4_addr_high; ip++) + { + IpAddress ipAddr(htonl(ip)); + if (opCmd == ADD) + { + addDnatPoolEntry(ipAddr.to_string()); + } + else + { + removeDnatPoolEntry(ipAddr.to_string()); + } + } +} + +/* To add a DNAT Pool entry */ +void NatMgr::addDnatPoolEntry(string destIp) +{ + + if (m_natDnatPoolInfo.find(destIp) != m_natDnatPoolInfo.end()) + { + /* Increment the ref count */ + m_natDnatPoolInfo[destIp] = (m_natDnatPoolInfo[destIp] + 1); + SWSS_LOG_INFO("Increased the ref count to %d for dnat pool entry %s", m_natDnatPoolInfo[destIp], destIp.c_str()); + } + else + { + /* Create the ref count */ + SWSS_LOG_INFO("Create the ref count for dnat pool entry %s", destIp.c_str()); + m_natDnatPoolInfo[destIp] = 1; + + std::vector values; + swss::FieldValueTuple p("NULL", "NULL"); + values.push_back(p); + m_appNatDnatPoolProducer.set(destIp, values); + } +} + +/* To remove a DNAT Pool */ +void NatMgr::removeDnatPoolEntry(string destIp) +{ + + if (m_natDnatPoolInfo.find(destIp) != m_natDnatPoolInfo.end()) + { + /* Decrement the ref count */ + m_natDnatPoolInfo[destIp] = (m_natDnatPoolInfo[destIp] - 1); + SWSS_LOG_INFO("Decreased the ref count to %d for dnat pool entry %s", m_natDnatPoolInfo[destIp], destIp.c_str()); + } + else + { + SWSS_LOG_INFO("Invalid DestIp DNAT pool removal for %s", destIp.c_str()); + return; + } + + if (!m_natDnatPoolInfo[destIp]) + { + m_natDnatPoolInfo.erase(destIp); + m_appNatDnatPoolProducer.del(destIp); + } +} + /* To add Static NAT entry based on Static Key if all valid conditions are met */ void NatMgr::addStaticNatEntry(const string &key) { @@ -1710,6 +1803,10 @@ void NatMgr::addStaticSingleNatEntry(const string &key) fvVectorDnat.push_back(q); } + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", appKeyDnat.c_str()); + addDnatPoolEntry(appKeyDnat); + FieldValueTuple r(NAT_TYPE, DNAT_NAT_TYPE); fvVectorDnat.push_back(r); FieldValueTuple s(NAT_TYPE, SNAT_NAT_TYPE); @@ -1818,6 +1915,13 @@ void NatMgr::addStaticTwiceNatEntry(const string &key) interface = m_staticNatEntry[key].interface; } + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", dest.c_str()); + addDnatPoolEntry(dest); + + SWSS_LOG_INFO("Adding dnat pool entry for %s", translated_src.c_str()); + addDnatPoolEntry(translated_src); + /* Create APPL_DB key and it's values */ string appKey = src + ":" + dest; string reverseAppKey = translated_dest + ":" + translated_src; @@ -1939,6 +2043,14 @@ void NatMgr::addStaticTwiceNatEntry(const string &key) m_natPoolInfo[pool_name].port_range, (*it).second.acl_name, (*it).first); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_staticNatEntry[key].local_ip.c_str()); + addDnatPoolEntry(m_staticNatEntry[key].local_ip); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(ADD, m_natPoolInfo[pool_name].ip_range); + break; } @@ -1991,6 +2103,10 @@ void NatMgr::addStaticSingleNaptEntry(const string &key) FieldValueTuple s(TRANSLATED_L4_PORT, keys[2]); fvVectorSnat.push_back(r); fvVectorSnat.push_back(s); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", keys[0].c_str()); + addDnatPoolEntry(keys[0]); } else if (m_staticNaptEntry[key].nat_type == SNAT_NAT_TYPE) { @@ -2005,6 +2121,10 @@ void NatMgr::addStaticSingleNaptEntry(const string &key) FieldValueTuple s(TRANSLATED_L4_PORT, keys[2]); fvVectorDnat.push_back(r); fvVectorDnat.push_back(s); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_staticNaptEntry[key].local_ip.c_str()); + addDnatPoolEntry(m_staticNaptEntry[key].local_ip); } FieldValueTuple t(NAT_TYPE, DNAT_NAT_TYPE); @@ -2139,6 +2259,13 @@ void NatMgr::addStaticTwiceNaptEntry(const string &key) interface = m_staticNaptEntry[key].interface; } + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", dest.c_str()); + addDnatPoolEntry(dest); + + SWSS_LOG_INFO("Adding dnat pool entry for %s", translated_src.c_str()); + addDnatPoolEntry(translated_src); + /* Create APPL_DB key and it's values */ string appKey = keys[1] + ":" + src + ":" + src_port + ":" + dest + ":" + dest_port; string reverseAppKey = keys[1] + ":" + translated_dest + ":" + translated_dest_port + ":" + translated_src + ":" + translated_src_port; @@ -2277,6 +2404,14 @@ void NatMgr::addStaticTwiceNaptEntry(const string &key) m_natPoolInfo[pool_name].port_range, (*it).second.acl_name, (*it).first); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_staticNaptEntry[key].local_ip.c_str()); + addDnatPoolEntry(m_staticNaptEntry[key].local_ip); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(ADD, m_natPoolInfo[pool_name].ip_range); + break; } @@ -2332,6 +2467,10 @@ void NatMgr::removeStaticSingleNatEntry(const string &key) appKeyDnat += m_staticNatEntry[key].local_ip; } + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", appKeyDnat.c_str()); + removeDnatPoolEntry(appKeyDnat); + /* Delete conntrack entry */ deleteConntrackSingleNatEntry(key); @@ -2438,6 +2577,13 @@ void NatMgr::removeStaticTwiceNatEntry(const string &key) interface = m_staticNatEntry[key].interface; } + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", dest.c_str()); + removeDnatPoolEntry(dest); + + SWSS_LOG_INFO("Deleting dnat pool entry for %s", translated_src.c_str()); + removeDnatPoolEntry(translated_src); + string appKey = src + ":" + dest; string reverseAppKey = translated_dest + ":" + translated_src; @@ -2551,6 +2697,14 @@ void NatMgr::removeStaticTwiceNatEntry(const string &key) setDynamicAllForwardOrAclbasedRules(DELETE, (*it).second.pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, (*it).first); + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_staticNatEntry[key].local_ip.c_str()); + removeDnatPoolEntry(m_staticNatEntry[key].local_ip); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, m_natPoolInfo[pool_name].ip_range); + (*it).second.twice_nat_added = false; (*it).second.static_key = EMPTY_STRING; m_staticNatEntry[key].twice_nat_added = false; @@ -2612,11 +2766,19 @@ void NatMgr::removeStaticSingleNaptEntry(const string &key) { appKeyDnat += (keys[1] + DEFAULT_KEY_SEPARATOR + keys[0] + DEFAULT_KEY_SEPARATOR + keys[2]); appKeySnat += (keys[1] + DEFAULT_KEY_SEPARATOR + m_staticNaptEntry[key].local_ip + DEFAULT_KEY_SEPARATOR + m_staticNaptEntry[key].local_port); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", keys[0].c_str()); + removeDnatPoolEntry(keys[0]); } else if (m_staticNaptEntry[key].nat_type == SNAT_NAT_TYPE) { appKeySnat += (keys[1] + DEFAULT_KEY_SEPARATOR + keys[0] + DEFAULT_KEY_SEPARATOR + keys[2]); appKeyDnat += (keys[1] + DEFAULT_KEY_SEPARATOR + m_staticNaptEntry[key].local_ip + DEFAULT_KEY_SEPARATOR + m_staticNaptEntry[key].local_port); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_staticNaptEntry[key].local_ip.c_str()); + removeDnatPoolEntry(m_staticNaptEntry[key].local_ip); } /* Delete conntrack entry */ @@ -2753,6 +2915,13 @@ void NatMgr::removeStaticTwiceNaptEntry(const string &key) interface = m_staticNaptEntry[key].interface; } + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", dest.c_str()); + removeDnatPoolEntry(dest); + + SWSS_LOG_INFO("Deleting dnat pool entry for %s", translated_src.c_str()); + removeDnatPoolEntry(translated_src); + string appKey = keys[1] + ":" + src + ":" + src_port + ":" + dest + ":" + dest_port; string reverseAppKey = keys[1] + ":" + translated_dest + ":" + translated_dest_port + ":" + translated_src + ":" + translated_src_port; @@ -2867,10 +3036,18 @@ void NatMgr::removeStaticTwiceNaptEntry(const string &key) setDynamicAllForwardOrAclbasedRules(DELETE, (*it).second.pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, (*it).first); + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_staticNaptEntry[key].local_ip.c_str()); + removeDnatPoolEntry(m_staticNaptEntry[key].local_ip); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, m_natPoolInfo[pool_name].ip_range); + (*it).second.twice_nat_added = false; (*it).second.static_key = EMPTY_STRING; - m_staticNatEntry[key].twice_nat_added = false; - m_staticNatEntry[key].binding_key = EMPTY_STRING; + m_staticNaptEntry[key].twice_nat_added = false; + m_staticNaptEntry[key].binding_key = EMPTY_STRING; isEntryDeleted = true; break; } @@ -4007,6 +4184,10 @@ void NatMgr::addDynamicNatRule(const string &key) SWSS_LOG_INFO("Adding dynamic single nat rules for %s", key.c_str()); setDynamicAllForwardOrAclbasedRules(ADD, pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, key); + + /* Add DnatPool entry to APPL_DB */ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(ADD, m_natPoolInfo[pool_name].ip_range); } else { @@ -4063,6 +4244,10 @@ void NatMgr::removeDynamicNatRule(const string &key) SWSS_LOG_INFO("Deleting dynamic single nat rules for %s", key.c_str()); setDynamicAllForwardOrAclbasedRules(DELETE, pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, key); + + /* Delete DNAT pool entry from APPL_DB */ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, m_natPoolInfo[pool_name].ip_range); } else { @@ -4177,6 +4362,10 @@ void NatMgr::addDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(DELETE, ip_range, port_range); + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, ip_range); + /* Set dynamic iptables rule without acl */ if (!setDynamicNatIptablesRulesWithoutAcl(DELETE, poolInterface, ip_range, port_range, (*it).second.static_key)) { @@ -4197,6 +4386,10 @@ void NatMgr::addDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(ADD, ip_range, port_range); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(ADD, ip_range); + /* Set dynamic iptables rule with acls*/ if (!setDynamicNatIptablesRulesWithAcl(ADD, poolInterface, ip_range, port_range, m_natAclRuleInfo[aclKey], (*it).second.static_key)) { @@ -4226,6 +4419,10 @@ void NatMgr::addDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(ADD, ip_range, port_range); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(ADD, ip_range); + /* Add dynamic iptables rule with acls */ if (!setDynamicNatIptablesRulesWithAcl(ADD, poolInterface, ip_range, port_range, (*it2).second, (*it).second.static_key)) { @@ -4244,6 +4441,10 @@ void NatMgr::addDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(DELETE, ip_range, port_range); + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, ip_range); + /* Delete dynamic iptables rule without acl */ if (!setDynamicNatIptablesRulesWithoutAcl(DELETE, poolInterface, ip_range, port_range, (*it).second.static_key)) { @@ -4361,6 +4562,10 @@ void NatMgr::removeDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(DELETE, ip_range, port_range); + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, ip_range); + /* Delete dynamic iptables rule with acls*/ if (!setDynamicNatIptablesRulesWithAcl(DELETE, poolInterface, ip_range, port_range, m_natAclRuleInfo[aclKey], (*it).second.static_key)) { @@ -4395,6 +4600,10 @@ void NatMgr::removeDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(ADD, ip_range, port_range); + /* Set DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(ADD, ip_range); + /* Set dynamic iptables rule without acl */ if (!setDynamicNatIptablesRulesWithoutAcl(ADD, poolInterface, ip_range, port_range, (*it).second.static_key)) { @@ -4427,6 +4636,10 @@ void NatMgr::removeDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(DELETE, ip_range, port_range); + /* Set DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, ip_range); + /* Delete dynamic iptables rule with acls */ if (!setDynamicNatIptablesRulesWithAcl(DELETE, poolInterface, ip_range, port_range, (*it2).second, (*it).second.static_key)) { @@ -4445,6 +4658,10 @@ void NatMgr::removeDynamicNatRuleByAcl(const string &aclKey, bool isRuleId) /* Set pool ip to APPL_DB */ setNaptPoolIpTable(ADD, ip_range, port_range); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", ip_range.c_str()); + setDnatPoolfromNatPool(ADD, ip_range); + /* Add dynamic iptables rule without acl */ if (!setDynamicNatIptablesRulesWithoutAcl(ADD, poolInterface, ip_range, port_range, (*it).second.static_key)) { @@ -4555,6 +4772,10 @@ void NatMgr::addDynamicNatRules(const string port, const string ipPrefix) setDynamicAllForwardOrAclbasedRules(ADD, pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, (*it).second.acl_name, (*it).first); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(ADD, m_natPoolInfo[pool_name].ip_range); } else { @@ -4667,6 +4888,10 @@ void NatMgr::removeDynamicNatRules(const string port, const string ipPrefix) setDynamicAllForwardOrAclbasedRules(DELETE, pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, (*it).second.acl_name, (*it).first); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, m_natPoolInfo[pool_name].ip_range); } else { @@ -4756,6 +4981,14 @@ void NatMgr::addDynamicTwiceNatRule(const string &key) setDynamicAllForwardOrAclbasedRules(ADD, m_natBindingInfo[key].pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, key); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", (*it).second.local_ip.c_str()); + addDnatPoolEntry((*it).second.local_ip); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(ADD, m_natPoolInfo[pool_name].ip_range); + isRuleAdded = true; break; } @@ -4798,6 +5031,14 @@ void NatMgr::addDynamicTwiceNatRule(const string &key) setDynamicAllForwardOrAclbasedRules(ADD, m_natBindingInfo[key].pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, key); + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", (*it).second.local_ip.c_str()); + addDnatPoolEntry((*it).second.local_ip); + + /* Add DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(ADD, m_natPoolInfo[pool_name].ip_range); + isRuleAdded = true; break; } @@ -4876,6 +5117,14 @@ void NatMgr::deleteDynamicTwiceNatRule(const string &key) setDynamicAllForwardOrAclbasedRules(DELETE, m_natBindingInfo[key].pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, key); + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Adding dnat pool entry for %s", (*it).second.local_ip.c_str()); + removeDnatPoolEntry((*it).second.local_ip); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, m_natPoolInfo[pool_name].ip_range); + (*it).second.twice_nat_added = false; (*it).second.binding_key = EMPTY_STRING; m_natBindingInfo[key].twice_nat_added = false; @@ -4923,6 +5172,14 @@ void NatMgr::deleteDynamicTwiceNatRule(const string &key) setDynamicAllForwardOrAclbasedRules(DELETE, m_natBindingInfo[key].pool_interface, m_natPoolInfo[pool_name].ip_range, m_natPoolInfo[pool_name].port_range, acls_name, key); + /* Delete DnatPool entry to APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", (*it).second.local_ip.c_str()); + removeDnatPoolEntry((*it).second.local_ip); + + /* Delete DnatPool entry from APPL_DB*/ + SWSS_LOG_INFO("Deleting dnat pool entry for %s", m_natPoolInfo[pool_name].ip_range.c_str()); + setDnatPoolfromNatPool(DELETE, m_natPoolInfo[pool_name].ip_range); + (*it).second.twice_nat_added = false; (*it).second.binding_key = EMPTY_STRING; m_natBindingInfo[key].twice_nat_added = false; diff --git a/cfgmgr/natmgr.h b/cfgmgr/natmgr.h index 8f6222a98f87..51b006f31abf 100644 --- a/cfgmgr/natmgr.h +++ b/cfgmgr/natmgr.h @@ -222,6 +222,12 @@ typedef std::map natAclRule_map_t; */ typedef std::map natZoneInterface_map_t; +/* To store NAT Dnat Pool information, + * Key is "Dst-Ip" (Eg. 65.55.45.1) + * Value is "ref_count" (Eg. 1) + */ +typedef std::map natDnatPool_map_t; + /* Define NatMgr Class inherited from Orch Class */ class NatMgr : public Orch { @@ -238,7 +244,7 @@ class NatMgr : public Orch private: /* Declare APPL_DB, CFG_DB and STATE_DB tables */ ProducerStateTable m_appNatTableProducer, m_appNaptTableProducer, m_appNatGlobalTableProducer; - ProducerStateTable m_appTwiceNatTableProducer, m_appTwiceNaptTableProducer; + ProducerStateTable m_appTwiceNatTableProducer, m_appTwiceNaptTableProducer, m_appNatDnatPoolProducer; Table m_statePortTable, m_stateLagTable, m_stateVlanTable, m_stateInterfaceTable, m_appNaptPoolIpTable; std::shared_ptr flushNotifier; @@ -256,6 +262,7 @@ class NatMgr : public Orch natZoneInterface_map_t m_natZoneInterfaceInfo; natAclTable_map_t m_natAclTableInfo; natAclRule_map_t m_natAclRuleInfo; + natDnatPool_map_t m_natDnatPoolInfo; /* Declare doTask related fucntions */ void doTask(Consumer &consumer); @@ -318,6 +325,9 @@ class NatMgr : public Orch void deleteDynamicTwiceNatRule(const std::string &key); void setDynamicAllForwardOrAclbasedRules(const std::string &opCmd, const std::string &pool_interface, const std::string &ip_range, const std::string &port_range, const std::string &acls_name, const std::string &dynamicKey); + void setDnatPoolfromNatPool(const std::string &opCmd, const std::string &ip_range); + void addDnatPoolEntry(std::string destIp); + void removeDnatPoolEntry(std::string destIp); bool isNatEnabled(void); bool isPortStateOk(const std::string &alias); diff --git a/orchagent/natorch.cpp b/orchagent/natorch.cpp index 69c0abb22279..595e99691c43 100644 --- a/orchagent/natorch.cpp +++ b/orchagent/natorch.cpp @@ -731,7 +731,7 @@ bool NatOrch::addHwDnatEntry(const IpAddress &ip_address) { uint32_t attr_count; sai_nat_entry_t dnat_entry; - sai_attribute_t nat_entry_attr[5]; + sai_attribute_t nat_entry_attr[4]; sai_status_t status; SWSS_LOG_ENTER(); @@ -747,23 +747,22 @@ bool NatOrch::addHwDnatEntry(const IpAddress &ip_address) memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); - nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; - nat_entry_attr[0].value.u32 = SAI_NAT_TYPE_DESTINATION_NAT; - nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_DST_IP; - nat_entry_attr[1].value.u32 = entry.translated_ip.getV4Addr(); - nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; - nat_entry_attr[2].value.u32 = 0xffffffff; - nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_DST_IP; + nat_entry_attr[0].value.u32 = entry.translated_ip.getV4Addr(); + nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; + nat_entry_attr[1].value.u32 = 0xffffffff; + nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[2].value.booldata = true; + nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; nat_entry_attr[3].value.booldata = true; - nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; - nat_entry_attr[4].value.booldata = true; - attr_count = 5; + attr_count = 4; memset(&dnat_entry, 0, sizeof(dnat_entry)); dnat_entry.vr_id = gVirtualRouterId; dnat_entry.switch_id = gSwitchId; + dnat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; dnat_entry.data.key.dst_ip = ip_address.getV4Addr(); dnat_entry.data.mask.dst_ip = 0xffffffff; @@ -804,7 +803,7 @@ bool NatOrch::addHwDnaptEntry(const NaptEntryKey &key) { uint32_t attr_count; sai_nat_entry_t dnat_entry; - sai_attribute_t nat_entry_attr[6]; + sai_attribute_t nat_entry_attr[5]; uint8_t ip_protocol = ((key.prototype == "TCP") ? IPPROTO_TCP : IPPROTO_UDP); sai_status_t status; @@ -823,25 +822,24 @@ bool NatOrch::addHwDnaptEntry(const NaptEntryKey &key) memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); - nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; - nat_entry_attr[0].value.u32 = SAI_NAT_TYPE_DESTINATION_NAT; - nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_DST_IP; - nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; - nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_L4_DST_PORT; - nat_entry_attr[1].value.u32 = entry.translated_ip.getV4Addr(); - nat_entry_attr[2].value.u32 = 0xffffffff; - nat_entry_attr[3].value.u16 = (uint16_t)(entry.translated_l4_port); - nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_DST_IP; + nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; + nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_L4_DST_PORT; + nat_entry_attr[0].value.u32 = entry.translated_ip.getV4Addr(); + nat_entry_attr[1].value.u32 = 0xffffffff; + nat_entry_attr[2].value.u16 = (uint16_t)(entry.translated_l4_port); + nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[3].value.booldata = true; + nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; nat_entry_attr[4].value.booldata = true; - nat_entry_attr[5].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; - nat_entry_attr[5].value.booldata = true; - attr_count = 6; + attr_count = 5; memset(&dnat_entry, 0, sizeof(dnat_entry)); dnat_entry.vr_id = gVirtualRouterId; dnat_entry.switch_id = gSwitchId; + dnat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; dnat_entry.data.key.dst_ip = key.ip_address.getV4Addr(); dnat_entry.data.key.l4_dst_port = (uint16_t)(key.l4_port); dnat_entry.data.mask.dst_ip = 0xffffffff; @@ -914,6 +912,7 @@ bool NatOrch::removeHwDnatEntry(const IpAddress &dstIp) dnat_entry.vr_id = gVirtualRouterId; dnat_entry.switch_id = gSwitchId; + dnat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; dnat_entry.data.key.dst_ip = dstIp.getV4Addr(); dnat_entry.data.mask.dst_ip = 0xffffffff; @@ -996,6 +995,7 @@ bool NatOrch::removeHwTwiceNatEntry(const TwiceNatEntryKey &key) dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.dst_ip = key.dst_ip.getV4Addr(); @@ -1088,6 +1088,7 @@ bool NatOrch::removeHwDnaptEntry(const NaptEntryKey &key) dnat_entry.vr_id = gVirtualRouterId; dnat_entry.switch_id = gSwitchId; + dnat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; dnat_entry.data.key.dst_ip = key.ip_address.getV4Addr(); dnat_entry.data.key.l4_dst_port = (uint16_t)(key.l4_port); dnat_entry.data.mask.dst_ip = 0xffffffff; @@ -1180,6 +1181,7 @@ bool NatOrch::removeHwTwiceNaptEntry(const TwiceNaptEntryKey &key) dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.l4_src_port = (uint16_t)(key.src_l4_port); @@ -1250,7 +1252,7 @@ bool NatOrch::addHwSnatEntry(const IpAddress &ip_address) { uint32_t attr_count; sai_nat_entry_t snat_entry; - sai_attribute_t nat_entry_attr[5]; + sai_attribute_t nat_entry_attr[4]; sai_status_t status; SWSS_LOG_ENTER(); @@ -1260,23 +1262,22 @@ bool NatOrch::addHwSnatEntry(const IpAddress &ip_address) memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); - nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; - nat_entry_attr[0].value.u32 = SAI_NAT_TYPE_SOURCE_NAT; - nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP; - nat_entry_attr[1].value.u32 = entry.translated_ip.getV4Addr(); - nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; - nat_entry_attr[2].value.u32 = 0xffffffff; - nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_SRC_IP; + nat_entry_attr[0].value.u32 = entry.translated_ip.getV4Addr(); + nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; + nat_entry_attr[1].value.u32 = 0xffffffff; + nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[2].value.booldata = true; + nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; nat_entry_attr[3].value.booldata = true; - nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; - nat_entry_attr[4].value.booldata = true; - attr_count = 5; + attr_count = 4; memset(&snat_entry, 0, sizeof(snat_entry)); snat_entry.vr_id = gVirtualRouterId; snat_entry.switch_id = gSwitchId; + snat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; snat_entry.data.key.src_ip = ip_address.getV4Addr(); snat_entry.data.mask.src_ip = 0xffffffff; @@ -1315,7 +1316,7 @@ bool NatOrch::addHwTwiceNatEntry(const TwiceNatEntryKey &key) { uint32_t attr_count; sai_nat_entry_t dbl_nat_entry; - sai_attribute_t nat_entry_attr[8]; + sai_attribute_t nat_entry_attr[6]; sai_status_t status; @@ -1326,27 +1327,26 @@ bool NatOrch::addHwTwiceNatEntry(const TwiceNatEntryKey &key) memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); - nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; - nat_entry_attr[0].value.u32 = SAI_NAT_TYPE_DOUBLE_NAT; - nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP; - nat_entry_attr[1].value.u32 = value.translated_src_ip.getV4Addr(); - nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; - nat_entry_attr[2].value.u32 = 0xffffffff; - nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_DST_IP; - nat_entry_attr[3].value.u32 = value.translated_dst_ip.getV4Addr(); - nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; - nat_entry_attr[4].value.u32 = 0xffffffff; - nat_entry_attr[5].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_SRC_IP; + nat_entry_attr[0].value.u32 = value.translated_src_ip.getV4Addr(); + nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; + nat_entry_attr[1].value.u32 = 0xffffffff; + nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_DST_IP; + nat_entry_attr[2].value.u32 = value.translated_dst_ip.getV4Addr(); + nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; + nat_entry_attr[3].value.u32 = 0xffffffff; + nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[4].value.booldata = true; + nat_entry_attr[5].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; nat_entry_attr[5].value.booldata = true; - nat_entry_attr[6].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; - nat_entry_attr[6].value.booldata = true; - attr_count = 7; + attr_count = 6; memset(&dbl_nat_entry, 0, sizeof(dbl_nat_entry)); dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.dst_ip = key.dst_ip.getV4Addr(); @@ -1397,7 +1397,7 @@ bool NatOrch::addHwSnaptEntry(const NaptEntryKey &keyEntry) { uint32_t attr_count; sai_nat_entry_t snat_entry; - sai_attribute_t nat_entry_attr[6]; + sai_attribute_t nat_entry_attr[5]; uint8_t ip_protocol = ((keyEntry.prototype == "TCP") ? IPPROTO_TCP : IPPROTO_UDP); sai_status_t status; @@ -1409,25 +1409,24 @@ bool NatOrch::addHwSnaptEntry(const NaptEntryKey &keyEntry) memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); - nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; - nat_entry_attr[0].value.u32 = SAI_NAT_TYPE_SOURCE_NAT; - nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP; - nat_entry_attr[1].value.u32 = entry.translated_ip.getV4Addr(); - nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; - nat_entry_attr[2].value.u32 = 0xffffffff; - nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_L4_SRC_PORT; - nat_entry_attr[3].value.u16 = (uint16_t)(entry.translated_l4_port); - nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_SRC_IP; + nat_entry_attr[0].value.u32 = entry.translated_ip.getV4Addr(); + nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; + nat_entry_attr[1].value.u32 = 0xffffffff; + nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_L4_SRC_PORT; + nat_entry_attr[2].value.u16 = (uint16_t)(entry.translated_l4_port); + nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[3].value.booldata = true; + nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; nat_entry_attr[4].value.booldata = true; - nat_entry_attr[5].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; - nat_entry_attr[5].value.booldata = true; - attr_count = 6; + attr_count = 5; memset(&snat_entry, 0, sizeof(snat_entry)); snat_entry.vr_id = gVirtualRouterId; snat_entry.switch_id = gSwitchId; + snat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; snat_entry.data.key.src_ip = keyEntry.ip_address.getV4Addr(); snat_entry.data.key.l4_src_port = (uint16_t)(keyEntry.l4_port); snat_entry.data.mask.src_ip = 0xffffffff; @@ -1472,7 +1471,7 @@ bool NatOrch::addHwTwiceNaptEntry(const TwiceNaptEntryKey &key) { uint32_t attr_count; sai_nat_entry_t dbl_nat_entry; - sai_attribute_t nat_entry_attr[10]; + sai_attribute_t nat_entry_attr[8]; uint8_t protoType = ((key.prototype == "TCP") ? IPPROTO_TCP : IPPROTO_UDP); sai_status_t status; @@ -1485,31 +1484,30 @@ bool NatOrch::addHwTwiceNaptEntry(const TwiceNaptEntryKey &key) memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); - nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; - nat_entry_attr[0].value.u32 = SAI_NAT_TYPE_DOUBLE_NAT; - nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP; - nat_entry_attr[1].value.u32 = value.translated_src_ip.getV4Addr(); - nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; - nat_entry_attr[2].value.u32 = 0xffffffff; - nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_L4_SRC_PORT; - nat_entry_attr[3].value.u16 = (uint16_t)(value.translated_src_l4_port); - nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_DST_IP; - nat_entry_attr[4].value.u32 = value.translated_dst_ip.getV4Addr(); - nat_entry_attr[5].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; - nat_entry_attr[5].value.u32 = 0xffffffff; - nat_entry_attr[6].id = SAI_NAT_ENTRY_ATTR_L4_DST_PORT; - nat_entry_attr[6].value.u16 = (uint16_t)(value.translated_dst_l4_port); - nat_entry_attr[7].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[0].id = SAI_NAT_ENTRY_ATTR_SRC_IP; + nat_entry_attr[0].value.u32 = value.translated_src_ip.getV4Addr(); + nat_entry_attr[1].id = SAI_NAT_ENTRY_ATTR_SRC_IP_MASK; + nat_entry_attr[1].value.u32 = 0xffffffff; + nat_entry_attr[2].id = SAI_NAT_ENTRY_ATTR_L4_SRC_PORT; + nat_entry_attr[2].value.u16 = (uint16_t)(value.translated_src_l4_port); + nat_entry_attr[3].id = SAI_NAT_ENTRY_ATTR_DST_IP; + nat_entry_attr[3].value.u32 = value.translated_dst_ip.getV4Addr(); + nat_entry_attr[4].id = SAI_NAT_ENTRY_ATTR_DST_IP_MASK; + nat_entry_attr[4].value.u32 = 0xffffffff; + nat_entry_attr[5].id = SAI_NAT_ENTRY_ATTR_L4_DST_PORT; + nat_entry_attr[5].value.u16 = (uint16_t)(value.translated_dst_l4_port); + nat_entry_attr[6].id = SAI_NAT_ENTRY_ATTR_ENABLE_PACKET_COUNT; + nat_entry_attr[6].value.booldata = true; + nat_entry_attr[7].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; nat_entry_attr[7].value.booldata = true; - nat_entry_attr[8].id = SAI_NAT_ENTRY_ATTR_ENABLE_BYTE_COUNT; - nat_entry_attr[8].value.booldata = true; - attr_count = 9; + attr_count = 8; memset(&dbl_nat_entry, 0, sizeof(dbl_nat_entry)); dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.l4_src_port = (uint16_t)(key.src_l4_port); @@ -1580,6 +1578,7 @@ bool NatOrch::removeHwSnatEntry(const IpAddress &ip_address) snat_entry.vr_id = gVirtualRouterId; snat_entry.switch_id = gSwitchId; + snat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; snat_entry.data.key.src_ip = ip_address.getV4Addr(); snat_entry.data.mask.src_ip = 0xffffffff; @@ -1663,6 +1662,7 @@ bool NatOrch::removeHwSnaptEntry(const NaptEntryKey &keyEntry) snat_entry.vr_id = gVirtualRouterId; snat_entry.switch_id = gSwitchId; + snat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; snat_entry.data.key.src_ip = keyEntry.ip_address.getV4Addr(); snat_entry.data.key.l4_src_port = (uint16_t)(keyEntry.l4_port); snat_entry.data.mask.src_ip = 0xffffffff; @@ -1727,6 +1727,90 @@ bool NatOrch::removeHwSnaptEntry(const NaptEntryKey &keyEntry) return true; } +// Add the DNAT Pool entry to the hardware +bool NatOrch::addHwDnatPoolEntry(const IpAddress &ip_address) +{ + uint32_t attr_count; + sai_nat_entry_t dnat_pool_entry; + sai_attribute_t nat_entry_attr[1]; + sai_status_t status; + + SWSS_LOG_ENTER(); + + if (!isNatEnabled()) + { + SWSS_LOG_WARN("NAT Feature is not yet enabled, skipped adding DNAT Pool entry with ip %s", ip_address.to_string().c_str()); + return true; + } + + SWSS_LOG_INFO("Create DNAT Pool entry for ip %s", ip_address.to_string().c_str()); + + memset(nat_entry_attr, 0, sizeof(nat_entry_attr)); + attr_count = 0; + + memset(&dnat_pool_entry, 0, sizeof(dnat_pool_entry)); + + dnat_pool_entry.vr_id = gVirtualRouterId; + dnat_pool_entry.switch_id = gSwitchId; + dnat_pool_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT_POOL; + dnat_pool_entry.data.key.dst_ip = ip_address.getV4Addr(); + dnat_pool_entry.data.mask.dst_ip = 0xffffffff; + + status = sai_nat_api->create_nat_entry(&dnat_pool_entry, attr_count, nat_entry_attr); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create DNAT Pool entry with ip %s", ip_address.to_string().c_str()); + + return false; + } + + SWSS_LOG_NOTICE("Created DNAT Pool entry with ip %s", ip_address.to_string().c_str()); + + return true; +} + +// Remove the DNAT Pool entry from the hardware +bool NatOrch::removeHwDnatPoolEntry(const IpAddress &dstIp) +{ + sai_nat_entry_t dnat_pool_entry; + sai_status_t status; + + SWSS_LOG_ENTER(); + SWSS_LOG_INFO("Deleting DNAT Pool entry ip %s from hardware", dstIp.to_string().c_str()); + + memset(&dnat_pool_entry, 0, sizeof(dnat_pool_entry)); + + dnat_pool_entry.vr_id = gVirtualRouterId; + dnat_pool_entry.switch_id = gSwitchId; + dnat_pool_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT_POOL; + dnat_pool_entry.data.key.dst_ip = dstIp.getV4Addr(); + dnat_pool_entry.data.mask.dst_ip = 0xffffffff; + + status = sai_nat_api->remove_nat_entry(&dnat_pool_entry); + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_INFO("Failed to remove DNAT Pool entry with ip %s", dstIp.to_string().c_str()); + + return false; + } + + SWSS_LOG_NOTICE("Removed DNAT Pool entry with ip %s", dstIp.to_string().c_str()); + + return true; +} + +void NatOrch::addAllDnatPoolEntries() +{ + SWSS_LOG_ENTER(); + + DnatPoolEntry::iterator dnatPoolIter = m_dnatPoolEntries.begin(); + while (dnatPoolIter != m_dnatPoolEntries.end()) + { + addHwDnatPoolEntry((*dnatPoolIter)); + dnatPoolIter++; + } +} + bool NatOrch::addNatEntry(const IpAddress &ip_address, const NatEntryValue &entry) { SWSS_LOG_ENTER(); @@ -2477,6 +2561,9 @@ void NatOrch::enableNatFeature(void) flushAllNatEntries(); } + SWSS_LOG_INFO("Adding DNAT Pool Entries "); + addAllDnatPoolEntries(); + SWSS_LOG_INFO("Adding NAT Entries "); addAllNatEntries(); @@ -2879,6 +2966,72 @@ void NatOrch::doNatGlobalTableTask(Consumer& consumer) } } +void NatOrch::doDnatPoolTableTask(Consumer& consumer) +{ + auto it = consumer.m_toSync.begin(); + while (it != consumer.m_toSync.end()) + { + KeyOpFieldsValuesTuple t = it->second; + string key = kfvKey(t); + string op = kfvOp(t); + vector keys = tokenize(key, ':'); + IpAddress global_address; + /* Example : APPL_DB + * NAT_DNAT_POOL_TABLE:65.55.45.1 + * NULL: NULL + */ + + /* Ensure the key size is 1 otherwise ignore */ + if (keys.size() != 1) + { + SWSS_LOG_ERROR("Invalid key size, skipping %s", key.c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + IpAddress ip_address = IpAddress(key); + + if (op == SET_COMMAND) + { + + if (m_dnatPoolEntries.find(ip_address) != m_dnatPoolEntries.end()) + { + SWSS_LOG_INFO("DNAT Pool entry found for ip %s", ip_address.to_string().c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + m_dnatPoolEntries.insert(ip_address); + + if (addHwDnatPoolEntry(ip_address)) + it = consumer.m_toSync.erase(it); + else + it++; + } + else if (op == DEL_COMMAND) + { + if (m_dnatPoolEntries.find(ip_address) == m_dnatPoolEntries.end()) + { + SWSS_LOG_INFO("DNAT Pool entry isn't found for ip %s", ip_address.to_string().c_str()); + it = consumer.m_toSync.erase(it); + continue; + } + + m_dnatPoolEntries.erase(ip_address); + + if (removeHwDnatPoolEntry(ip_address)) + it = consumer.m_toSync.erase(it); + else + it++; + } + else + { + SWSS_LOG_ERROR("Unknown operation type %s\n", op.c_str()); + it = consumer.m_toSync.erase(it); + } + } +} + void NatOrch::doTask(Consumer& consumer) { SWSS_LOG_ENTER(); @@ -2912,6 +3065,11 @@ void NatOrch::doTask(Consumer& consumer) SWSS_LOG_INFO("Received APP_NAT_GLOBAL_TABLE_NAME update"); doNatGlobalTableTask(consumer); } + else if (table_name == APP_NAT_DNAT_POOL_TABLE_NAME) + { + SWSS_LOG_INFO("Received APP_NAT_DNAT_POOL_TABLE_NAME update"); + doDnatPoolTableTask(consumer); + } else { SWSS_LOG_INFO("Received unknown NAT Table - %s notification", table_name.c_str()); @@ -3298,11 +3456,13 @@ bool NatOrch::getNatCounters(const NatEntry::iterator &iter) if (entry.nat_type == "dnat") { + nat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; nat_entry.data.key.dst_ip = ipAddr.getV4Addr(); nat_entry.data.mask.dst_ip = 0xffffffff; } else { + nat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; nat_entry.data.key.src_ip = ipAddr.getV4Addr(); nat_entry.data.mask.src_ip = 0xffffffff; } @@ -3368,6 +3528,7 @@ bool NatOrch::getTwiceNatCounters(const TwiceNatEntry::iterator &iter) dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.dst_ip = key.dst_ip.getV4Addr(); @@ -3420,11 +3581,13 @@ bool NatOrch::setNatCounters(const NatEntry::iterator &iter) if (entry.nat_type == "dnat") { + nat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; nat_entry.data.key.dst_ip = ipAddr.getV4Addr(); nat_entry.data.mask.dst_ip = 0xffffffff; } else { + nat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; nat_entry.data.key.src_ip = ipAddr.getV4Addr(); nat_entry.data.mask.src_ip = 0xffffffff; } @@ -3499,6 +3662,7 @@ bool NatOrch::getNaptCounters(const NaptEntry::iterator &iter) if (entry.nat_type == "dnat") { + nat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; nat_entry.data.key.dst_ip = naptKey.ip_address.getV4Addr(); nat_entry.data.key.l4_dst_port = (uint16_t)(naptKey.l4_port); nat_entry.data.mask.dst_ip = 0xffffffff; @@ -3506,6 +3670,7 @@ bool NatOrch::getNaptCounters(const NaptEntry::iterator &iter) } else if (entry.nat_type == "snat") { + nat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; nat_entry.data.key.src_ip = naptKey.ip_address.getV4Addr(); nat_entry.data.key.l4_src_port = (uint16_t)(naptKey.l4_port); nat_entry.data.mask.src_ip = 0xffffffff; @@ -3581,6 +3746,7 @@ bool NatOrch::getTwiceNaptCounters(const TwiceNaptEntry::iterator &iter) dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.l4_src_port = (uint16_t)(key.src_l4_port); @@ -3641,6 +3807,7 @@ bool NatOrch::setNaptCounters(const NaptEntry::iterator &iter) if (entry.nat_type == "dnat") { + nat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; nat_entry.data.key.dst_ip = naptKey.ip_address.getV4Addr(); nat_entry.data.key.l4_dst_port = (uint16_t)(naptKey.l4_port); nat_entry.data.mask.dst_ip = 0xffffffff; @@ -3648,6 +3815,7 @@ bool NatOrch::setNaptCounters(const NaptEntry::iterator &iter) } else if (entry.nat_type == "snat") { + nat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; nat_entry.data.key.src_ip = naptKey.ip_address.getV4Addr(); nat_entry.data.key.l4_src_port = (uint16_t)(naptKey.l4_port); nat_entry.data.mask.src_ip = 0xffffffff; @@ -3727,6 +3895,7 @@ bool NatOrch::setTwiceNatCounters(const TwiceNatEntry::iterator &iter) dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.dst_ip = key.dst_ip.getV4Addr(); @@ -3781,6 +3950,7 @@ bool NatOrch::setTwiceNaptCounters(const TwiceNaptEntry::iterator &iter) dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.l4_src_port = (uint16_t)(key.src_l4_port); @@ -4018,6 +4188,7 @@ bool NatOrch::checkIfNatEntryIsActive(const NatEntry::iterator &iter, time_t now snat_entry.vr_id = gVirtualRouterId; snat_entry.switch_id = gSwitchId; + snat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; srcIp = ipAddr; snat_entry.data.key.src_ip = srcIp.getV4Addr(); snat_entry.data.mask.src_ip = 0xffffffff; @@ -4050,6 +4221,7 @@ bool NatOrch::checkIfNatEntryIsActive(const NatEntry::iterator &iter, time_t now dnat_entry.vr_id = gVirtualRouterId; dnat_entry.switch_id = gSwitchId; + dnat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; dnat_entry.data.key.dst_ip = entry.translated_ip.getV4Addr(); dnat_entry.data.mask.dst_ip = 0xffffffff; @@ -4112,6 +4284,7 @@ bool NatOrch::checkIfNaptEntryIsActive(const NaptEntry::iterator &iter, time_t n snat_entry.vr_id = gVirtualRouterId; snat_entry.switch_id = gSwitchId; + snat_entry.nat_type = SAI_NAT_TYPE_SOURCE_NAT; srcIp = naptKey.ip_address; srcPort = (uint16_t)(naptKey.l4_port); @@ -4156,6 +4329,7 @@ bool NatOrch::checkIfNaptEntryIsActive(const NaptEntry::iterator &iter, time_t n dnat_entry.vr_id = gVirtualRouterId; dnat_entry.switch_id = gSwitchId; + dnat_entry.nat_type = SAI_NAT_TYPE_DESTINATION_NAT; dnat_entry.data.key.dst_ip = entry.translated_ip.getV4Addr(); dnat_entry.data.key.l4_dst_port = (uint16_t)(entry.translated_l4_port); @@ -4215,6 +4389,7 @@ bool NatOrch::checkIfTwiceNatEntryIsActive(const TwiceNatEntry::iterator &iter, dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.dst_ip = key.dst_ip.getV4Addr(); @@ -4269,6 +4444,7 @@ bool NatOrch::checkIfTwiceNaptEntryIsActive(const TwiceNaptEntry::iterator &iter dbl_nat_entry.vr_id = gVirtualRouterId; dbl_nat_entry.switch_id = gSwitchId; + dbl_nat_entry.nat_type = SAI_NAT_TYPE_DOUBLE_NAT; dbl_nat_entry.data.key.src_ip = key.src_ip.getV4Addr(); dbl_nat_entry.data.mask.src_ip = 0xffffffff; dbl_nat_entry.data.key.l4_src_port = (uint16_t)(key.src_l4_port); diff --git a/orchagent/natorch.h b/orchagent/natorch.h index b0fb88cd40cf..313a4deb2f9f 100644 --- a/orchagent/natorch.h +++ b/orchagent/natorch.h @@ -160,6 +160,9 @@ typedef std::set DnaptCache; typedef std::set TwiceNatCache; typedef std::set TwiceNaptCache; +// Cache of DNAT Pool destIp +typedef std::set DnatPoolEntry; + struct DnatEntries { IpAddress dnatIp; /* NAT entry cache */ @@ -217,6 +220,8 @@ class NatOrch: public Orch, public Subject, public Observer mutex m_natMutex; string m_dbgCompName; IpAddress nullIpv4Addr; + DnatPoolEntry m_dnatPoolEntries; + /* DNAT/DNAPT entry is cached, to delete and re-add it whenever the direct NextHop (connected neighbor) * or indirect NextHop (via route) to reach the DNAT IP is changed. */ @@ -247,6 +252,7 @@ class NatOrch: public Orch, public Subject, public Observer void doTwiceNatTableTask(Consumer& consumer); void doTwiceNaptTableTask(Consumer& consumer); void doNatGlobalTableTask(Consumer& consumer); + void doDnatPoolTableTask(Consumer& consumer); bool addNatEntry(const IpAddress &ip_address, const NatEntryValue &entry); bool removeNatEntry(const IpAddress &ip_address); @@ -282,6 +288,8 @@ class NatOrch: public Orch, public Subject, public Observer bool addHwDnaptEntry(const NaptEntryKey &key); bool removeHwDnatEntry(const IpAddress &dstIp); bool removeHwDnaptEntry(const NaptEntryKey &key); + bool addHwDnatPoolEntry(const IpAddress &dstIp); + bool removeHwDnatPoolEntry(const IpAddress &dstIp); void addAllStaticConntrackEntries(void); void addConnTrackEntry(const IpAddress &ipAddr); @@ -308,6 +316,7 @@ class NatOrch: public Orch, public Subject, public Observer void disableNatFeature(void); void addAllNatEntries(void); void flushAllNatEntries(void); + void addAllDnatPoolEntries(void); void clearAllDnatEntries(void); void cleanupAppDbEntries(void); void clearCounters(void); diff --git a/orchagent/orchdaemon.cpp b/orchagent/orchdaemon.cpp index 6782a1608719..6b4ceeaa01de 100644 --- a/orchagent/orchdaemon.cpp +++ b/orchagent/orchdaemon.cpp @@ -214,11 +214,12 @@ bool OrchDaemon::init() const int natorch_base_pri = 50; vector nat_tables = { - { APP_NAT_TABLE_NAME, natorch_base_pri + 4 }, - { APP_NAPT_TABLE_NAME, natorch_base_pri + 3 }, - { APP_NAT_TWICE_TABLE_NAME, natorch_base_pri + 2 }, - { APP_NAPT_TWICE_TABLE_NAME, natorch_base_pri + 1 }, - { APP_NAT_GLOBAL_TABLE_NAME, natorch_base_pri } + { APP_NAT_DNAT_POOL_TABLE_NAME, natorch_base_pri + 5 }, + { APP_NAT_TABLE_NAME, natorch_base_pri + 4 }, + { APP_NAPT_TABLE_NAME, natorch_base_pri + 3 }, + { APP_NAT_TWICE_TABLE_NAME, natorch_base_pri + 2 }, + { APP_NAPT_TWICE_TABLE_NAME, natorch_base_pri + 1 }, + { APP_NAT_GLOBAL_TABLE_NAME, natorch_base_pri } }; gNatOrch = new NatOrch(m_applDb, m_stateDb, nat_tables, gRouteOrch, gNeighOrch); diff --git a/tests/test_nat.py b/tests/test_nat.py index 9dea37aeb3db..8d277b9be2ab 100644 --- a/tests/test_nat.py +++ b/tests/test_nat.py @@ -116,7 +116,8 @@ def test_AddNatStaticEntry(self, dvs, testlog): #check the entry in asic db tbl = swsscommon.Table(self.asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY") keys = tbl.getKeys() - assert len(keys) == 2 + # Keys should be 3, SNAT, DNAT and DNAT Pool entries + assert len(keys) == 3 for key in keys: if (key.find("dst_ip:67.66.65.1")) or (key.find("src_ip:18.18.18.2")): @@ -177,7 +178,8 @@ def test_AddNaPtStaticEntry(self, dvs, testlog): #check the entry in asic db tbl = swsscommon.Table(self.asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY") keys = tbl.getKeys() - assert len(keys) == 2 + # Keys should be 3, SNAT, DNAT and DNAT Pool entries + assert len(keys) == 3 for key in keys: if (key.find("dst_ip:67.66.65.1")) and (key.find("key.l4_dst_port:670")): @@ -251,7 +253,8 @@ def test_AddTwiceNatEntry(self, dvs, testlog): #check the entry in asic db tbl = swsscommon.Table(self.asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY") keys = tbl.getKeys() - assert len(keys) == 2 + # Keys should be 4, SNAT, DNAT and 2 DNAT Pool entries + assert len(keys) == 4 for key in keys: if (key.find("dst_ip:18.18.18.1")) or (key.find("src_ip:18.18.18.2")): assert True @@ -324,7 +327,8 @@ def test_AddTwiceNaPtEntry(self, dvs, testlog): #check the entry in asic db tbl = swsscommon.Table(self.asicdb, "ASIC_STATE:SAI_OBJECT_TYPE_NAT_ENTRY") keys = tbl.getKeys() - assert len(keys) == 2 + # Keys should be 4, SNAT, DNAT and 2 DNAT Pool entries + assert len(keys) == 4 for key in keys: if (key.find("src_ip:18.18.18.2")) or (key.find("l4_src_port:182")): assert True