Skip to content

Commit 0811214

Browse files
authored
Validate destination port is not LAG (sonic-net#2053)
* Validate destination port is not LAG * Enhance to support mirroring of source port rx/tx to different destination ports
1 parent 6ab1c51 commit 0811214

File tree

3 files changed

+122
-26
lines changed

3 files changed

+122
-26
lines changed

config/main.py

+37-26
Original file line numberDiff line numberDiff line change
@@ -829,18 +829,36 @@ def interface_is_in_portchannel(portchannel_member_table, interface_name):
829829

830830
return False
831831

832-
def interface_has_mirror_config(mirror_table, interface_name):
833-
""" Check if port is already configured with mirror config """
834-
for _, v in mirror_table.items():
835-
if 'src_port' in v and v['src_port'] == interface_name:
832+
def check_mirror_direction_config(v, direction):
833+
""" Check if port is already configured for mirror in same direction """
834+
if direction:
835+
direction=direction.upper()
836+
if ('direction' in v and v['direction'] == 'BOTH') or (direction == 'BOTH'):
836837
return True
837-
if 'dst_port' in v and v['dst_port'] == interface_name:
838+
if 'direction' in v and v['direction'] == direction:
838839
return True
840+
else:
841+
return True
842+
843+
def interface_has_mirror_config(ctx, mirror_table, dst_port, src_port, direction):
844+
""" Check if dst/src port is already configured with mirroring in same direction """
845+
for _, v in mirror_table.items():
846+
if src_port:
847+
for port in src_port.split(","):
848+
if 'dst_port' in v and v['dst_port'] == port:
849+
ctx.fail("Error: Source Interface {} already has mirror config".format(port))
850+
if 'src_port' in v and re.search(port,v['src_port']):
851+
if check_mirror_direction_config(v, direction):
852+
ctx.fail("Error: Source Interface {} already has mirror config in same direction".format(port))
853+
if dst_port:
854+
if ('dst_port' in v and v['dst_port'] == dst_port) or ('src_port' in v and re.search(dst_port,v['src_port'])):
855+
ctx.fail("Error: Destination Interface {} already has mirror config".format(dst_port))
839856

840857
return False
841858

842859
def validate_mirror_session_config(config_db, session_name, dst_port, src_port, direction):
843860
""" Check if SPAN mirror-session config is valid """
861+
ctx = click.get_current_context()
844862
if len(config_db.get_entry('MIRROR_SESSION', session_name)) != 0:
845863
click.echo("Error: {} already exists".format(session_name))
846864
return False
@@ -851,41 +869,34 @@ def validate_mirror_session_config(config_db, session_name, dst_port, src_port,
851869

852870
if dst_port:
853871
if not interface_name_is_valid(config_db, dst_port):
854-
click.echo("Error: Destination Interface {} is invalid".format(dst_port))
855-
return False
872+
ctx.fail("Error: Destination Interface {} is invalid".format(dst_port))
873+
874+
if is_portchannel_present_in_db(config_db, dst_port):
875+
ctx.fail("Error: Destination Interface {} is not supported".format(dst_port))
856876

857877
if interface_is_in_vlan(vlan_member_table, dst_port):
858-
click.echo("Error: Destination Interface {} has vlan config".format(dst_port))
859-
return False
878+
ctx.fail("Error: Destination Interface {} has vlan config".format(dst_port))
860879

861-
if interface_has_mirror_config(mirror_table, dst_port):
862-
click.echo("Error: Destination Interface {} already has mirror config".format(dst_port))
863-
return False
864880

865881
if interface_is_in_portchannel(portchannel_member_table, dst_port):
866-
click.echo("Error: Destination Interface {} has portchannel config".format(dst_port))
867-
return False
882+
ctx.fail("Error: Destination Interface {} has portchannel config".format(dst_port))
868883

869884
if clicommon.is_port_router_interface(config_db, dst_port):
870-
click.echo("Error: Destination Interface {} is a L3 interface".format(dst_port))
871-
return False
885+
ctx.fail("Error: Destination Interface {} is a L3 interface".format(dst_port))
872886

873887
if src_port:
874888
for port in src_port.split(","):
875889
if not interface_name_is_valid(config_db, port):
876-
click.echo("Error: Source Interface {} is invalid".format(port))
877-
return False
890+
ctx.fail("Error: Source Interface {} is invalid".format(port))
878891
if dst_port and dst_port == port:
879-
click.echo("Error: Destination Interface cant be same as Source Interface")
880-
return False
881-
if interface_has_mirror_config(mirror_table, port):
882-
click.echo("Error: Source Interface {} already has mirror config".format(port))
883-
return False
892+
ctx.fail("Error: Destination Interface cant be same as Source Interface")
893+
894+
if interface_has_mirror_config(ctx, mirror_table, dst_port, src_port, direction):
895+
return False
884896

885897
if direction:
886898
if direction not in ['rx', 'tx', 'both']:
887-
click.echo("Error: Direction {} is invalid".format(direction))
888-
return False
899+
ctx.fail("Error: Direction {} is invalid".format(direction))
889900

890901
return True
891902

@@ -2086,7 +2097,7 @@ def add_span(session_name, dst_port, src_port, direction, queue, policer):
20862097
dst_port = interface_alias_to_name(None, dst_port)
20872098
if dst_port is None:
20882099
click.echo("Error: Destination Interface {} is invalid".format(dst_port))
2089-
return
2100+
return False
20902101

20912102
session_info = {
20922103
"type" : "SPAN",

tests/config_mirror_session_test.py

+80
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,88 @@ def test_mirror_session_span_add():
164164
assert result.exit_code != 0
165165
assert ERR_MSG_VALUE_FAILURE in result.stdout
166166

167+
# Verify invalid dst port
168+
result = runner.invoke(
169+
config.config.commands["mirror_session"].commands["span"].commands["add"],
170+
["test_session", "Ethern", "Ethernet4", "rx", "100"])
171+
assert result.exit_code != 0
172+
assert "Error: Destination Interface Ethern is invalid" in result.stdout
173+
174+
# Verify destination port not have vlan config
175+
result = runner.invoke(
176+
config.config.commands["mirror_session"].commands["span"].commands["add"],
177+
["test_session", "Ethernet24", "Ethernet4", "rx", "100"])
178+
assert result.exit_code != 0
179+
assert "Error: Destination Interface Ethernet24 has vlan config" in result.stdout
180+
181+
# Verify destination port is not part of portchannel
182+
result = runner.invoke(
183+
config.config.commands["mirror_session"].commands["span"].commands["add"],
184+
["test_session", "Ethernet116", "Ethernet4", "rx", "100"])
185+
assert result.exit_code != 0
186+
assert "Error: Destination Interface Ethernet116 has portchannel config" in result.stdout
187+
188+
# Verify destination port not router interface
189+
result = runner.invoke(
190+
config.config.commands["mirror_session"].commands["span"].commands["add"],
191+
["test_session", "Ethernet0", "Ethernet4", "rx", "100"])
192+
assert result.exit_code != 0
193+
assert "Error: Destination Interface Ethernet0 is a L3 interface" in result.stdout
194+
195+
# Verify destination port not Portchannel
196+
result = runner.invoke(
197+
config.config.commands["mirror_session"].commands["span"].commands["add"],
198+
["test_session", "PortChannel1001"])
199+
assert result.exit_code != 0
200+
assert "Error: Destination Interface PortChannel1001 is not supported" in result.output
201+
202+
# Verify source interface is invalid
203+
result = runner.invoke(
204+
config.config.commands["mirror_session"].commands["span"].commands["add"],
205+
["test_session", "Ethernet52", "Ethern", "rx", "100"])
206+
assert result.exit_code != 0
207+
assert "Error: Source Interface Ethern is invalid" in result.stdout
208+
209+
# Verify source interface is not same as destination
210+
result = runner.invoke(
211+
config.config.commands["mirror_session"].commands["span"].commands["add"],
212+
["test_session", "Ethernet52", "Ethernet52", "rx", "100"])
213+
assert result.exit_code != 0
214+
assert "Error: Destination Interface cant be same as Source Interface" in result.stdout
215+
216+
# Verify destination port not have mirror config
217+
result = runner.invoke(
218+
config.config.commands["mirror_session"].commands["span"].commands["add"],
219+
["test_session", "Ethernet44", "Ethernet56", "rx", "100"])
220+
assert result.exit_code != 0
221+
assert "Error: Destination Interface Ethernet44 already has mirror config" in result.output
222+
223+
# Verify source port is not configured as dstport in other session
224+
result = runner.invoke(
225+
config.config.commands["mirror_session"].commands["span"].commands["add"],
226+
["test_session", "Ethernet52", "Ethernet44", "rx", "100"])
227+
assert result.exit_code != 0
228+
assert "Error: Source Interface Ethernet44 already has mirror config" in result.output
229+
230+
# Verify source port is not configured in same direction
231+
result = runner.invoke(
232+
config.config.commands["mirror_session"].commands["span"].commands["add"],
233+
["test_session", "Ethernet52", "Ethernet8,Ethernet40", "rx", "100"])
234+
assert result.exit_code != 0
235+
assert "Error: Source Interface Ethernet40 already has mirror config in same direction" in result.output
236+
237+
# Verify direction is invalid
238+
result = runner.invoke(
239+
config.config.commands["mirror_session"].commands["span"].commands["add"],
240+
["test_session", "Ethernet52", "Ethernet56", "px", "100"])
241+
assert result.exit_code != 0
242+
assert "Error: Direction px is invalid" in result.stdout
243+
167244
# Positive case
168245
with mock.patch('config.main.add_span') as mocked:
246+
result = runner.invoke(
247+
config.config.commands["mirror_session"].commands["span"].commands["add"],
248+
["test_session", "Ethernet8", "Ethernet4", "tx", "100"])
169249
result = runner.invoke(
170250
config.config.commands["mirror_session"].commands["span"].commands["add"],
171251
["test_session", "Ethernet0", "Ethernet4", "rx", "100"])

tests/mock_tables/config_db.json

+5
Original file line numberDiff line numberDiff line change
@@ -2553,5 +2553,10 @@
25532553
},
25542554
"QUEUE|Ethernet96|6": {
25552555
"scheduler": "[SCHEDULER|scheduler.0]"
2556+
},
2557+
"MIRROR_SESSION|test_session_db1": {
2558+
"dst_port": "Ethernet44",
2559+
"src_port": "Ethernet40,Ethernet48",
2560+
"direction": "RX"
25562561
}
25572562
}

0 commit comments

Comments
 (0)