test_pim6_prune_propagate.py::PIM6PrunePropagate
IPv6 PIM prune propagation test.
This test primarily checks two things:
- prunes must not be delayed unnecessarily
- MFIB state must be removed in response to prunes
As a necessity, this sets up a traffic flow first.
- ::startup
- ::prepare:#91:r1/pim6d/vtysh[show ipv6 pim neighbor json]
- ::prepare:#91:r2/pim6d/vtysh[show ipv6 pim neighbor json]
- ::prepare:#91:r3/pim6d/vtysh[show ipv6 pim neighbor json]
- ::prepare:#91:r4/pim6d/vtysh[show ipv6 pim neighbor json]
- ::join_traffic:#126#116:h1/scapy[h1-lan1/IPv6/UDP]
- ::join_traffic:#130:h4/h4-lan4/multicast-join[fdbc:1::fc05:ff:febc:100,ff35::2345]
- ::join_traffic:#132:r4/pim6d/log
- ::join_traffic:#139:r3/pim6d/log
- ::join_traffic:#139:r2/pim6d/log
- ::join_traffic:#139:r1/pim6d/log
- ::join_traffic:#148#116:h1/scapy[h1-lan1/IPv6/UDP]
- ::join_traffic:#157:lan4/packet
- ::join_traffic:#159#108:r1/pim6d/vtysh[show ipv6 pim join json]
- ::join_traffic:#160#108:r2/pim6d/vtysh[show ipv6 pim join json]
- ::join_traffic:#161#108:r3/pim6d/vtysh[show ipv6 pim join json]
- ::join_traffic:#163#108:r4/pim6d/vtysh[show ipv6 pim join json]
- ::mld_wait:#172:h4/h4-lan4/multicast-leave[fdbc:1::fc05:ff:febc:100,ff35::2345]
- ::mld_wait:#173:r4/pim6d/log
- ::mld_wait:#179:r4/pim6d/log
- ::prune:#192#108:r1/pim6d/vtysh[show ipv6 pim join json]
- ::prune:#193#108:r2/pim6d/vtysh[show ipv6 pim join json]
- ::prune:#194#108:r3/pim6d/vtysh[show ipv6 pim join json]
- ::prune:#196#108:r4/pim6d/vtysh[show ipv6 pim join json]
- ::prune:#199#116:h1/scapy[h1-lan1/IPv6/UDP]
- ::prune:#202:r4/pim6d/vtysh[show ipv6 mroute json]
- ::prune:#205:r3/pim6d/vtysh[show ipv6 mroute json]
- ::prune:#208:r2/pim6d/vtysh[show ipv6 mroute json]
- ::prune:#213:r1/pim6d/vtysh[show ipv6 mroute json]
- ::prune:#227#116:h1/scapy[h1-lan1/IPv6/UDP]
- ::shutdown
::startup
passed after 2.10s
('test_pim6_prune_propagate.py', -inf, 'startup')
::prepare
Wait for PIM neighbors to come up.
::prepare:#91:r1/pim6d/vtysh[show ipv6 pim neighbor json]
passed after 0.60s, CLI command: show ipv6 pim neighbor json
Expected output:
{'r1-r2': {'fe80::fc02:ff:fefe:100': {}}}('test_pim6_prune_propagate.py', 91, '#91:r1/pim6d/vtysh[show ipv6 pim neighbor json]')
::prepare:#91:r2/pim6d/vtysh[show ipv6 pim neighbor json]
passed after 0.00s, CLI command: show ipv6 pim neighbor json
Expected output:
{'r2-r1': {'fe80::fc01:ff:fefe:200': {}}, 'r2-r3': {'fe80::fc03:ff:fefe:200': {}}}('test_pim6_prune_propagate.py', 91, '#91:r2/pim6d/vtysh[show ipv6 pim neighbor json]')
::prepare:#91:r3/pim6d/vtysh[show ipv6 pim neighbor json]
passed after 0.00s, CLI command: show ipv6 pim neighbor json
Expected output:
{'r3-r2': {'fe80::fc02:ff:fefe:300': {}}, 'r3-r4': {'fe80::fc04:ff:fefe:300': {}}}('test_pim6_prune_propagate.py', 91, '#91:r3/pim6d/vtysh[show ipv6 pim neighbor json]')
::prepare:#91:r4/pim6d/vtysh[show ipv6 pim neighbor json]
passed after 0.00s, CLI command: show ipv6 pim neighbor json
Expected output:
{'r4-r3': {'fe80::fc03:ff:fefe:400': {}}}('test_pim6_prune_propagate.py', 91, '#91:r4/pim6d/vtysh[show ipv6 pim neighbor json]')
::join_traffic
Join S,G and push some traffic through.
::join_traffic:#126#116:h1/scapy[h1-lan1/IPv6/UDP]
passed after 0.27s, packet: Ether / IPv6 / UDP IPv6Address('fdbc:1::fc05:ff:febc:100'):9999 > ff35::2345:9999
###[ Ethernet ]### dst = 33:33:00:00:23:45 src = None type = IPv6 ###[ IPv6 ]### version = 6 tc = 0 fl = 0 plen = None nh = UDP hlim = 255 src = IPv6Address('fdbc:1::fc05:ff:febc:100') dst = ff35::2345 ###[ UDP ]### sport = 9999 dport = 9999 len = None chksum = None
::join_traffic:#130:h4/h4-lan4/multicast-join[fdbc:1::fc05:ff:febc:100,ff35::2345]
passed after 0.00s
('test_pim6_prune_propagate.py', 130, '#130:h4/h4-lan4/multicast-join[fdbc:1::fc05:ff:febc:100,ff35::2345]')
::join_traffic:#132:r4/pim6d/log
passed after 0.01s
('test_pim6_prune_propagate.py', 132, '#132:r4/pim6d/log')
::join_traffic:#139:r3/pim6d/log
passed after 0.00s
('test_pim6_prune_propagate.py', 139, '#139:r3/pim6d/log')
::join_traffic:#139:r2/pim6d/log
passed after 0.00s
('test_pim6_prune_propagate.py', 139, '#139:r2/pim6d/log')
::join_traffic:#139:r1/pim6d/log
passed after 0.00s
('test_pim6_prune_propagate.py', 139, '#139:r1/pim6d/log')
::join_traffic:#148#116:h1/scapy[h1-lan1/IPv6/UDP]
passed after 33.08s, packet: Ether / IPv6 / UDP IPv6Address('fdbc:1::fc05:ff:febc:100'):9999 > ff35::2345:9999
###[ Ethernet ]### dst = 33:33:00:00:23:45 src = None type = IPv6 ###[ IPv6 ]### version = 6 tc = 0 fl = 0 plen = None nh = UDP hlim = 255 src = IPv6Address('fdbc:1::fc05:ff:febc:100') dst = ff35::2345 ###[ UDP ]### sport = 9999 dport = 9999 len = None chksum = None
::join_traffic:#157:lan4/packet
passed after 0.00s
('test_pim6_prune_propagate.py', 157, '#157:lan4/packet')
::join_traffic:#159#108:r1/pim6d/vtysh[show ipv6 pim join json]
passed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r1-r2': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'JOIN'}}}}('test_pim6_prune_propagate.py', 159, '#159#108:r1/pim6d/vtysh[show ipv6 pim join json]')
::join_traffic:#160#108:r2/pim6d/vtysh[show ipv6 pim join json]
passed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r2-r3': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'JOIN'}}}}('test_pim6_prune_propagate.py', 160, '#160#108:r2/pim6d/vtysh[show ipv6 pim join json]')
::join_traffic:#161#108:r3/pim6d/vtysh[show ipv6 pim join json]
passed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r3-r4': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'JOIN'}}}}('test_pim6_prune_propagate.py', 161, '#161#108:r3/pim6d/vtysh[show ipv6 pim join json]')
::join_traffic:#163#108:r4/pim6d/vtysh[show ipv6 pim join json]
passed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r4-lan4': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'NOINFO'}}}}('test_pim6_prune_propagate.py', 163, '#163#108:r4/pim6d/vtysh[show ipv6 pim join json]')
::mld_wait
Give MLD 10 seconds to age out the join.
(Timing: query-max-response-time + robustness * interval)
::mld_wait:#172:h4/h4-lan4/multicast-leave[fdbc:1::fc05:ff:febc:100,ff35::2345]
passed after 0.00s
('test_pim6_prune_propagate.py', 172, '#172:h4/h4-lan4/multicast-leave[fdbc:1::fc05:ff:febc:100,ff35::2345]')
::mld_wait:#173:r4/pim6d/log
passed after 0.01s
('test_pim6_prune_propagate.py', 173, '#173:r4/pim6d/log')
::mld_wait:#179:r4/pim6d/log
passed after 1.31s
('test_pim6_prune_propagate.py', 179, '#179:r4/pim6d/log')
::prune
Ensure the PIM prune propagates and applies without unexpected delays.
::prune:#192#108:r1/pim6d/vtysh[show ipv6 pim join json]
failed after 1.00s, CLI command: show ipv6 pim join json
Expected output:
{'r1-r2': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'NOINFO'}}}}('test_pim6_prune_propagate.py', 192, '#192#108:r1/pim6d/vtysh[show ipv6 pim join json]')
self = <test_pim6_prune_propagate.PIM6PrunePropagate object at 0x7f776531bd50>, topo = <topotato.toponom.Network object at 0x7f7765a000d0>, r1 = <Router 1 "r1">, r2 = <Router 2 "r2"> r3 = <Router 3 "r3">, r4 = <Router 4 "r4">, h1 = <Router 5 "h1">, h4 = <Router 6 "h4"> @topotatofunc def prune(self, topo, r1, r2, r3, r4, h1, h4): """ Ensure the PIM prune propagates and applies without unexpected delays. """ # r2 & r3 go through NOINFO for a little while for prune handling > yield from self.assert_join_state(r1, "r1-r2", "NOINFO", maxwait=1.0) E topotato.exceptions.TopotatoCLICompareFail: json["r1-r2"]["ff35::2345"]["fdbc:1::fc05:ff:febc:100"]["channelJoinName"] dict value is different ( E --- Expected value E +++ Current value E @@ -1 +1 @@ E -"NOINFO" E +"JOIN") /home/equinox/python/topotato/test_pim6_prune_propagate.py:192: TopotatoCLICompareFail
::prune:#193#108:r2/pim6d/vtysh[show ipv6 pim join json]
failed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r2-r3': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'NOINFO'}}}}('test_pim6_prune_propagate.py', 193, '#193#108:r2/pim6d/vtysh[show ipv6 pim join json]')
self = <test_pim6_prune_propagate.PIM6PrunePropagate object at 0x7f776531bd50>, topo = <topotato.toponom.Network object at 0x7f7765a000d0>, r1 = <Router 1 "r1">, r2 = <Router 2 "r2"> r3 = <Router 3 "r3">, r4 = <Router 4 "r4">, h1 = <Router 5 "h1">, h4 = <Router 6 "h4"> @topotatofunc def prune(self, topo, r1, r2, r3, r4, h1, h4): """ Ensure the PIM prune propagates and applies without unexpected delays. """ # r2 & r3 go through NOINFO for a little while for prune handling yield from self.assert_join_state(r1, "r1-r2", "NOINFO", maxwait=1.0) > yield from self.assert_join_state(r2, "r2-r3", "NOINFO", maxwait=1.0) E topotato.exceptions.TopotatoCLICompareFail: json["r2-r3"]["ff35::2345"]["fdbc:1::fc05:ff:febc:100"]["channelJoinName"] dict value is different ( E --- Expected value E +++ Current value E @@ -1 +1 @@ E -"NOINFO" E +"JOIN") /home/equinox/python/topotato/test_pim6_prune_propagate.py:193: TopotatoCLICompareFail
::prune:#194#108:r3/pim6d/vtysh[show ipv6 pim join json]
passed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r3-r4': {'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'channelJoinName': 'NOINFO'}}}}('test_pim6_prune_propagate.py', 194, '#194#108:r3/pim6d/vtysh[show ipv6 pim join json]')
::prune:#196#108:r4/pim6d/vtysh[show ipv6 pim join json]
passed after 0.00s, CLI command: show ipv6 pim join json
Expected output:
{'r4-lan4': None}('test_pim6_prune_propagate.py', 196, '#196#108:r4/pim6d/vtysh[show ipv6 pim join json]')
::prune:#199#116:h1/scapy[h1-lan1/IPv6/UDP]
passed after 2.06s, packet: Ether / IPv6 / UDP IPv6Address('fdbc:1::fc05:ff:febc:100'):9999 > ff35::2345:9999
###[ Ethernet ]### dst = 33:33:00:00:23:45 src = None type = IPv6 ###[ IPv6 ]### version = 6 tc = 0 fl = 0 plen = None nh = UDP hlim = 255 src = IPv6Address('fdbc:1::fc05:ff:febc:100') dst = ff35::2345 ###[ UDP ]### sport = 9999 dport = 9999 len = None chksum = None
::prune:#202:r4/pim6d/vtysh[show ipv6 mroute json]
passed after 0.00s, CLI command: show ipv6 mroute json
Expected output:
{'ff35::2345': None}('test_pim6_prune_propagate.py', 202, '#202:r4/pim6d/vtysh[show ipv6 mroute json]')
::prune:#205:r3/pim6d/vtysh[show ipv6 mroute json]
failed after 0.93s, CLI command: show ipv6 mroute json
Expected output:
{'ff35::2345': None}('test_pim6_prune_propagate.py', 205, '#205:r3/pim6d/vtysh[show ipv6 mroute json]')
self = <test_pim6_prune_propagate.PIM6PrunePropagate object at 0x7f776531bd50>, topo = <topotato.toponom.Network object at 0x7f7765a000d0>, r1 = <Router 1 "r1">, r2 = <Router 2 "r2"> r3 = <Router 3 "r3">, r4 = <Router 4 "r4">, h1 = <Router 5 "h1">, h4 = <Router 6 "h4"> @topotatofunc def prune(self, topo, r1, r2, r3, r4, h1, h4): """ Ensure the PIM prune propagates and applies without unexpected delays. """ # r2 & r3 go through NOINFO for a little while for prune handling yield from self.assert_join_state(r1, "r1-r2", "NOINFO", maxwait=1.0) yield from self.assert_join_state(r2, "r2-r3", "NOINFO", maxwait=1.0) yield from self.assert_join_state(r3, "r3-r4", "NOINFO", maxwait=1.0) # MLD state is gone yield from self.assert_join_state(r4, "r4-lan4", None, maxwait=1.0) # send some follow-on packets that should NOT get forwarded yield from self.pkt_send(h1, repeat=3, interval=1) # r2-4 should completely ditch source MFIB state yield from AssertVtysh.make( r4, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) > yield from AssertVtysh.make( r3, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) E topotato.exceptions.TopotatoCLICompareFail: "ff35::2345" should not exist in json (have {'ff35::2345'}): E --- Expected value E +++ Current value E @@ -1 +1,12 @@ E -null E +{ E + "fdbc:1::fc05:ff:febc:100": { E + "group": "ff35::2345", E + "iif": "r3-r2", E + "installed": 1, E + "oilInheritedRescan": 0, E + "oilSize": 0, E + "refCount": 1, E + "source": "fdbc:1::fc05:ff:febc:100", E + "upTime": "00:00:38" E + } E +} /home/equinox/python/topotato/test_pim6_prune_propagate.py:205: TopotatoCLICompareFail
::prune:#208:r2/pim6d/vtysh[show ipv6 mroute json]
failed after 0.00s, CLI command: show ipv6 mroute json
Expected output:
{'ff35::2345': None}('test_pim6_prune_propagate.py', 208, '#208:r2/pim6d/vtysh[show ipv6 mroute json]')
self = <test_pim6_prune_propagate.PIM6PrunePropagate object at 0x7f776531bd50>, topo = <topotato.toponom.Network object at 0x7f7765a000d0>, r1 = <Router 1 "r1">, r2 = <Router 2 "r2"> r3 = <Router 3 "r3">, r4 = <Router 4 "r4">, h1 = <Router 5 "h1">, h4 = <Router 6 "h4"> @topotatofunc def prune(self, topo, r1, r2, r3, r4, h1, h4): """ Ensure the PIM prune propagates and applies without unexpected delays. """ # r2 & r3 go through NOINFO for a little while for prune handling yield from self.assert_join_state(r1, "r1-r2", "NOINFO", maxwait=1.0) yield from self.assert_join_state(r2, "r2-r3", "NOINFO", maxwait=1.0) yield from self.assert_join_state(r3, "r3-r4", "NOINFO", maxwait=1.0) # MLD state is gone yield from self.assert_join_state(r4, "r4-lan4", None, maxwait=1.0) # send some follow-on packets that should NOT get forwarded yield from self.pkt_send(h1, repeat=3, interval=1) # r2-4 should completely ditch source MFIB state yield from AssertVtysh.make( r4, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) yield from AssertVtysh.make( r3, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) > yield from AssertVtysh.make( r2, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) E topotato.exceptions.TopotatoCLICompareFail: "ff35::2345" should not exist in json (have {'ff35::2345'}): E --- Expected value E +++ Current value E @@ -1 +1,26 @@ E -null E +{ E + "fdbc:1::fc05:ff:febc:100": { E + "flags": "ST", E + "group": "ff35::2345", E + "iif": "r2-r1", E + "installed": 1, E + "oil": { E + "r2-r3": { E + "group": "ff35::2345", E + "iVifI": 1, E + "inboundInterface": "r2-r1", E + "oVifI": 2, E + "outboundInterface": "r2-r3", E + "protocolPim": true, E + "source": "fdbc:1::fc05:ff:febc:100", E + "ttl": 1, E + "upTime": "00:00:38" E + } E + }, E + "oilInheritedRescan": 0, E + "oilSize": 1, E + "refCount": 1, E + "source": "fdbc:1::fc05:ff:febc:100", E + "upTime": "00:00:38" E + } E +} /home/equinox/python/topotato/test_pim6_prune_propagate.py:208: TopotatoCLICompareFail
::prune:#213:r1/pim6d/vtysh[show ipv6 mroute json]
failed after 0.00s, CLI command: show ipv6 mroute json
Expected output:
{'ff35::2345': {'fdbc:1::fc05:ff:febc:100': {'oilSize': 0}}}('test_pim6_prune_propagate.py', 213, '#213:r1/pim6d/vtysh[show ipv6 mroute json]')
self = <test_pim6_prune_propagate.PIM6PrunePropagate object at 0x7f776531bd50>, topo = <topotato.toponom.Network object at 0x7f7765a000d0>, r1 = <Router 1 "r1">, r2 = <Router 2 "r2"> r3 = <Router 3 "r3">, r4 = <Router 4 "r4">, h1 = <Router 5 "h1">, h4 = <Router 6 "h4"> @topotatofunc def prune(self, topo, r1, r2, r3, r4, h1, h4): """ Ensure the PIM prune propagates and applies without unexpected delays. """ # r2 & r3 go through NOINFO for a little while for prune handling yield from self.assert_join_state(r1, "r1-r2", "NOINFO", maxwait=1.0) yield from self.assert_join_state(r2, "r2-r3", "NOINFO", maxwait=1.0) yield from self.assert_join_state(r3, "r3-r4", "NOINFO", maxwait=1.0) # MLD state is gone yield from self.assert_join_state(r4, "r4-lan4", None, maxwait=1.0) # send some follow-on packets that should NOT get forwarded yield from self.pkt_send(h1, repeat=3, interval=1) # r2-4 should completely ditch source MFIB state yield from AssertVtysh.make( r4, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) yield from AssertVtysh.make( r3, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) yield from AssertVtysh.make( r2, "pim6d", "show ipv6 mroute json", {"ff35::2345": None}, maxwait=4.0 ) # r1 remembers the source but must have an empty OIL now > yield from AssertVtysh.make( r1, "pim6d", "show ipv6 mroute json", { "ff35::2345": { str(self.srcaddr): { "oilSize": 0, }, }, }, maxwait=4.0, ) E topotato.exceptions.TopotatoCLICompareFail: json["ff35::2345"]["fdbc:1::fc05:ff:febc:100"]["oilSize"] dict value is different ( E --- Expected value E +++ Current value E @@ -1 +1 @@ E -0 E +1) /home/equinox/python/topotato/test_pim6_prune_propagate.py:213: TopotatoCLICompareFail
::prune:#227#116:h1/scapy[h1-lan1/IPv6/UDP]
passed after 0.26s, packet: Ether / IPv6 / UDP IPv6Address('fdbc:1::fc05:ff:febc:100'):9999 > ff35::2345:9999
###[ Ethernet ]### dst = 33:33:00:00:23:45 src = None type = IPv6 ###[ IPv6 ]### version = 6 tc = 0 fl = 0 plen = None nh = UDP hlim = 255 src = IPv6Address('fdbc:1::fc05:ff:febc:100') dst = ff35::2345 ###[ UDP ]### sport = 9999 dport = 9999 len = None chksum = None
::shutdown
passed after 1.29s
('test_pim6_prune_propagate.py', inf, 'shutdown')