Skip to content

Commit 5043701

Browse files
authored
Add support for IP interface loopback action (sonic-net#2307)
* Add IP interface loopback action support Co-authored-by: liora <liora@nvidia.com>
1 parent fe875fd commit 5043701

File tree

5 files changed

+193
-7
lines changed

5 files changed

+193
-7
lines changed

cfgmgr/intfmgr.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
728728
string grat_arp = "";
729729
string mpls = "";
730730
string ipv6_link_local_mode = "";
731+
string loopback_action = "";
731732

732733
for (auto idx : data)
733734
{
@@ -770,6 +771,10 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
770771
{
771772
vlanId = value;
772773
}
774+
else if (field == "loopback_action")
775+
{
776+
loopback_action = value;
777+
}
773778
}
774779

775780
if (op == SET_COMMAND)
@@ -811,6 +816,13 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
811816
data.push_back(fvTuple);
812817
}
813818

819+
/* Set loopback action */
820+
if (!loopback_action.empty())
821+
{
822+
FieldValueTuple fvTuple("loopback_action", loopback_action);
823+
data.push_back(fvTuple);
824+
}
825+
814826
/* Set mpls */
815827
if (!setIntfMpls(alias, mpls))
816828
{

orchagent/intfsorch.cpp

+81-4
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,37 @@ bool IntfsOrch::setIntfProxyArp(const string &alias, const string &proxy_arp)
416416
return true;
417417
}
418418

419+
bool IntfsOrch::setIntfLoopbackAction(const Port &port, string actionStr)
420+
{
421+
sai_attribute_t attr;
422+
sai_packet_action_t action;
423+
424+
if (!getSaiLoopbackAction(actionStr, action))
425+
{
426+
return false;
427+
}
428+
429+
attr.id = SAI_ROUTER_INTERFACE_ATTR_LOOPBACK_PACKET_ACTION;
430+
attr.value.s32 = action;
431+
432+
sai_status_t status = sai_router_intfs_api->set_router_interface_attribute(port.m_rif_id, &attr);
433+
if (status != SAI_STATUS_SUCCESS)
434+
{
435+
SWSS_LOG_ERROR("Loopback action [%s] set failed, interface [%s], rc [%d]",
436+
actionStr.c_str(), port.m_alias.c_str(), status);
437+
438+
task_process_status handle_status = handleSaiSetStatus(SAI_API_ROUTER_INTERFACE, status);
439+
if (handle_status != task_success)
440+
{
441+
return parseHandleSaiStatusFailure(handle_status);
442+
}
443+
}
444+
445+
SWSS_LOG_NOTICE("Loopback action [%s] set success, interface [%s]",
446+
actionStr.c_str(), port.m_alias.c_str());
447+
return true;
448+
}
449+
419450
set<IpPrefix> IntfsOrch:: getSubnetRoutes()
420451
{
421452
SWSS_LOG_ENTER();
@@ -433,7 +464,9 @@ set<IpPrefix> IntfsOrch:: getSubnetRoutes()
433464
return subnet_routes;
434465
}
435466

436-
bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPrefix *ip_prefix, const bool adminUp, const uint32_t mtu)
467+
bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPrefix *ip_prefix,
468+
const bool adminUp, const uint32_t mtu, string loopbackAction)
469+
437470
{
438471
SWSS_LOG_ENTER();
439472

@@ -443,7 +476,7 @@ bool IntfsOrch::setIntf(const string& alias, sai_object_id_t vrf_id, const IpPre
443476
auto it_intfs = m_syncdIntfses.find(alias);
444477
if (it_intfs == m_syncdIntfses.end())
445478
{
446-
if (!ip_prefix && addRouterIntfs(vrf_id, port))
479+
if (!ip_prefix && addRouterIntfs(vrf_id, port, loopbackAction))
447480
{
448481
gPortsOrch->increasePortRefCount(alias);
449482
IntfsEntry intfs_entry;
@@ -665,6 +698,7 @@ void IntfsOrch::doTask(Consumer &consumer)
665698
string inband_type = "";
666699
bool mpls = false;
667700
string vlan = "";
701+
string loopbackAction = "";
668702

669703
for (auto idx : data)
670704
{
@@ -757,6 +791,10 @@ void IntfsOrch::doTask(Consumer &consumer)
757791
{
758792
vlan = value;
759793
}
794+
else if (field == "loopback_action")
795+
{
796+
loopbackAction = value;
797+
}
760798
}
761799

762800
if (alias == "eth0" || alias == "docker0")
@@ -874,7 +912,8 @@ void IntfsOrch::doTask(Consumer &consumer)
874912
{
875913
adminUp = port.m_admin_state_up;
876914
}
877-
if (!setIntf(alias, vrf_id, ip_prefix_in_key ? &ip_prefix : nullptr, adminUp, mtu))
915+
916+
if (!setIntf(alias, vrf_id, ip_prefix_in_key ? &ip_prefix : nullptr, adminUp, mtu, loopbackAction))
878917
{
879918
it++;
880919
continue;
@@ -906,6 +945,12 @@ void IntfsOrch::doTask(Consumer &consumer)
906945
setRouterIntfsMpls(port);
907946
gPortsOrch->setPort(alias, port);
908947
}
948+
949+
/* Set loopback action */
950+
if (!loopbackAction.empty())
951+
{
952+
setIntfLoopbackAction(port, loopbackAction);
953+
}
909954
}
910955
}
911956

@@ -1047,7 +1092,28 @@ void IntfsOrch::doTask(Consumer &consumer)
10471092
}
10481093
}
10491094

1050-
bool IntfsOrch::addRouterIntfs(sai_object_id_t vrf_id, Port &port)
1095+
bool IntfsOrch::getSaiLoopbackAction(const string &actionStr, sai_packet_action_t &action)
1096+
{
1097+
const unordered_map<string, sai_packet_action_t> loopbackActionMap =
1098+
{
1099+
{"drop", SAI_PACKET_ACTION_DROP},
1100+
{"forward", SAI_PACKET_ACTION_FORWARD},
1101+
};
1102+
1103+
auto it = loopbackActionMap.find(actionStr);
1104+
if (it != loopbackActionMap.end())
1105+
{
1106+
action = loopbackActionMap.at(actionStr);
1107+
return true;
1108+
}
1109+
else
1110+
{
1111+
SWSS_LOG_WARN("Unsupported loopback action [%s]", actionStr.c_str());
1112+
return false;
1113+
}
1114+
}
1115+
1116+
bool IntfsOrch::addRouterIntfs(sai_object_id_t vrf_id, Port &port, string loopbackActionStr)
10511117
{
10521118
SWSS_LOG_ENTER();
10531119

@@ -1067,6 +1133,17 @@ bool IntfsOrch::addRouterIntfs(sai_object_id_t vrf_id, Port &port)
10671133
attr.value.oid = vrf_id;
10681134
attrs.push_back(attr);
10691135

1136+
if (!loopbackActionStr.empty())
1137+
{
1138+
sai_packet_action_t loopbackAction;
1139+
if (getSaiLoopbackAction(loopbackActionStr, loopbackAction))
1140+
{
1141+
attr.id = SAI_ROUTER_INTERFACE_ATTR_LOOPBACK_PACKET_ACTION;
1142+
attr.value.s32 = loopbackAction;
1143+
attrs.push_back(attr);
1144+
}
1145+
}
1146+
10701147
attr.id = SAI_ROUTER_INTERFACE_ATTR_SRC_MAC_ADDRESS;
10711148
if (port.m_mac)
10721149
{

orchagent/intfsorch.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ class IntfsOrch : public Orch
5454
void addRifToFlexCounter(const string&, const string&, const string&);
5555
void removeRifFromFlexCounter(const string&, const string&);
5656

57-
bool setIntf(const string& alias, sai_object_id_t vrf_id = gVirtualRouterId, const IpPrefix *ip_prefix = nullptr, const bool adminUp = true, const uint32_t mtu = 0);
57+
bool setIntfLoopbackAction(const Port &port, string actionStr);
58+
bool getSaiLoopbackAction(const string &actionStr, sai_packet_action_t &action);
59+
bool setIntf(const string& alias, sai_object_id_t vrf_id = gVirtualRouterId, const IpPrefix *ip_prefix = nullptr, const bool adminUp = true, const uint32_t mtu = 0, string loopbackAction = "");
5860
bool removeIntf(const string& alias, sai_object_id_t vrf_id = gVirtualRouterId, const IpPrefix *ip_prefix = nullptr);
5961

6062
void addIp2MeRoute(sai_object_id_t vrf_id, const IpPrefix &ip_prefix);
@@ -95,7 +97,7 @@ class IntfsOrch : public Orch
9597
std::string getRifRateInitTableKey(std::string s);
9698
void cleanUpRifFromCounterDb(const string &id, const string &name);
9799

98-
bool addRouterIntfs(sai_object_id_t vrf_id, Port &port);
100+
bool addRouterIntfs(sai_object_id_t vrf_id, Port &port, string loopbackAction);
99101
bool removeRouterIntfs(Port &port);
100102

101103
void addDirectedBroadcast(const Port &port, const IpPrefix &ip_prefix);

orchagent/port.h

-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,6 @@ class Port
151151
sai_port_interface_type_t m_interface_type;
152152
std::vector<uint32_t> m_adv_interface_types;
153153
bool m_mpls = false;
154-
155154
/*
156155
* Following bit vector is used to lock
157156
* the queue from being changed in BufferOrch.

tests/test_interface.py

+96
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from swsscommon import swsscommon
66

7+
VLAN_SUB_INTERFACE_SEPARATOR = '.'
8+
79
class TestRouterInterface(object):
810
def setup_db(self, dvs):
911
self.pdb = swsscommon.DBConnector(0, dvs.redis_sock, 0)
@@ -2193,6 +2195,100 @@ def test_VLanInterfaceIpv6LinkLocalOnly(self, dvs, testlog):
21932195
# one loopback router interface
21942196
assert len(intf_entries) == 1
21952197

2198+
def set_loopback_action(self, interface, action):
2199+
if interface.startswith("PortChannel"):
2200+
tbl_name = "PORTCHANNEL_INTERFACE"
2201+
elif interface.startswith("Vlan"):
2202+
tbl_name = "VLAN_INTERFACE"
2203+
else:
2204+
sub_intf_sep_idx = interface.find(VLAN_SUB_INTERFACE_SEPARATOR)
2205+
if sub_intf_sep_idx != -1:
2206+
tbl_name = "VLAN_SUB_INTERFACE"
2207+
else:
2208+
tbl_name = "INTERFACE"
2209+
2210+
fvs = swsscommon.FieldValuePairs([("loopback_action", action)])
2211+
tbl = swsscommon.Table(self.cdb, tbl_name)
2212+
tbl.set(interface, fvs)
2213+
time.sleep(1)
2214+
2215+
def loopback_action_test(self, iface, action):
2216+
# create interface
2217+
self.create_l3_intf(iface, "")
2218+
2219+
# set interface loopback action in config db
2220+
self.set_loopback_action(iface, action)
2221+
2222+
# check application database
2223+
tbl = swsscommon.Table(self.pdb, "INTF_TABLE")
2224+
(status, fvs) = tbl.get(iface)
2225+
assert status == True
2226+
2227+
action_found = False
2228+
for fv in fvs:
2229+
if fv[0] == "loopback_action":
2230+
action_found = True
2231+
assert fv[1] == action
2232+
assert action_found == True
2233+
2234+
# check asic db
2235+
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_ROUTER_INTERFACE")
2236+
intf_entries = tbl.getKeys()
2237+
2238+
action_map = {"drop": "SAI_PACKET_ACTION_DROP", "forward": "SAI_PACKET_ACTION_FORWARD"}
2239+
action_found = False
2240+
for key in intf_entries:
2241+
(status, fvs) = tbl.get(key)
2242+
assert status == True
2243+
2244+
for fv in fvs:
2245+
if fv[0] == "SAI_ROUTER_INTERFACE_ATTR_LOOPBACK_PACKET_ACTION":
2246+
action_found = True
2247+
assert fv[1] == action_map[action]
2248+
assert action_found == True
2249+
2250+
# remove interface
2251+
self.remove_l3_intf(iface)
2252+
2253+
def test_interfaceLoopbackActionDrop(self, dvs, testlog):
2254+
self.setup_db(dvs)
2255+
self.loopback_action_test("Ethernet8", "drop")
2256+
2257+
def test_interfaceLoopbackActionForward(self, dvs, testlog):
2258+
self.setup_db(dvs)
2259+
self.loopback_action_test("Ethernet8", "forward")
2260+
2261+
def test_subInterfaceLoopbackActionDrop(self, dvs, testlog):
2262+
self.setup_db(dvs)
2263+
self.loopback_action_test("Ethernet8.1", "drop")
2264+
2265+
def test_subInterfaceLoopbackActionForward(self, dvs, testlog):
2266+
self.setup_db(dvs)
2267+
self.loopback_action_test("Ethernet8.1", "forward")
2268+
2269+
def test_vlanInterfaceLoopbackActionDrop(self, dvs, testlog):
2270+
self.setup_db(dvs)
2271+
self.create_vlan("10")
2272+
self.loopback_action_test("Vlan10", "drop")
2273+
self.remove_vlan("10")
2274+
2275+
def test_vlanInterfaceLoopbackActionForward(self, dvs, testlog):
2276+
self.setup_db(dvs)
2277+
self.create_vlan("20")
2278+
self.loopback_action_test("Vlan20", "forward")
2279+
self.remove_vlan("20")
2280+
2281+
def test_portChannelInterfaceLoopbackActionDrop(self, dvs, testlog):
2282+
self.setup_db(dvs)
2283+
self.create_port_channel("PortChannel009")
2284+
self.loopback_action_test("PortChannel009", "drop")
2285+
self.remove_port_channel("PortChannel009")
2286+
2287+
def test_portChannelInterfaceLoopbackActionForward(self, dvs, testlog):
2288+
self.setup_db(dvs)
2289+
self.create_port_channel("PortChannel010")
2290+
self.loopback_action_test("PortChannel010", "forward")
2291+
self.remove_port_channel("PortChannel010")
21962292

21972293
# Add Dummy always-pass test at end as workaroud
21982294
# for issue when Flaky fail on final test it invokes module tear-down before retrying

0 commit comments

Comments
 (0)