Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 1 | # SPDX-FileCopyrightText: Copyright 2021-present Open Networking Foundation. |
| 2 | # SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | |
| 4 | class INT: |
| 5 | |
| 6 | def __init__(self): |
| 7 | self.default = "" |
| 8 | |
| 9 | def CASE1 (self, main): |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 10 | main.case("Send ping packets from one host to another host and check flows from DeepInsight") |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 11 | import time |
| 12 | import socket |
| 13 | from core import utilities |
| 14 | from tests.USECASE.SegmentRouting.INT.dependencies.IntTest import IntTest |
| 15 | main.cfgName = "CASE1" |
| 16 | |
| 17 | main.step("Setting up the test") |
| 18 | intTest = IntTest(scapy=True) |
| 19 | intTest.setUpTest(main) |
| 20 | |
| 21 | main.step("Setting up hosts and variables") |
| 22 | srcIfaceName = main.h1.interfaces[0]["name"] |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 23 | srcMac = main.h1.getMac(srcIfaceName) |
Yi Tseng | f34ec00 | 2022-02-28 15:56:44 -0800 | [diff] [blame] | 24 | dstMac = main.params.get("routerMac", "00:00:00:00:00:00") |
Yi Tseng | 69cdb17 | 2022-02-23 10:52:10 -0800 | [diff] [blame] | 25 | srcIp = main.h1.interfaces[0]['ips'][0] |
| 26 | dstIp = main.h2.interfaces[0]['ips'][0] |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 27 | srcPort = 2000 |
| 28 | dstPort = 8888 |
| 29 | |
| 30 | main.step("Send ping packets from h1 to h2") |
| 31 | startTimeMs = (time.time() - 5) * 1000 |
| 32 | pkt = """( |
| 33 | Ether(src="{}", dst="{}") / |
| 34 | IP(src="{}", dst="{}") / |
| 35 | UDP(sport={}, dport={}) / |
| 36 | ("A"*30) |
| 37 | )""".format(srcMac, dstMac, srcIp, dstIp, srcPort, dstPort) |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 38 | # Send multiple packets incase the server or DeepInsight drop the report accidently |
| 39 | # FIXME: Find the root cause, might be misconfiguration or Linux(e.g., rp_filter?) issue. |
| 40 | for _ in range(0, 5): |
| 41 | main.h1.sendPacket(iface=srcIfaceName, packet=pkt) |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 42 | endTimeMs = (time.time() + 5) * 1000 |
| 43 | |
| 44 | main.step("Checking total number of flow reports from DeepInsight") |
| 45 | def getFiveTupleCount(*args, **kwargs): |
| 46 | flows = main.DeepInsight.getFlows( |
| 47 | startTimeMs=startTimeMs, |
| 48 | endTimeMs=endTimeMs, |
| 49 | srcIp=srcIp, |
| 50 | dstIp=dstIp, |
| 51 | ipProto=socket.IPPROTO_UDP |
| 52 | ) |
| 53 | if "FiveTupleCount" in flows: |
| 54 | return flows["FiveTupleCount"] |
| 55 | else: |
| 56 | return 0 |
| 57 | # Need to wait few seconds until DeepInsight database updated. |
| 58 | fiveTupleCount = utilities.retry( |
| 59 | f=getFiveTupleCount, |
| 60 | retValue=0, |
| 61 | attempts=60, |
| 62 | ) |
| 63 | |
| 64 | utilities.assert_equals( |
| 65 | expect=1, actual=fiveTupleCount, |
| 66 | onpass="Got 1 flow report from DeepInsight as expected.", |
| 67 | onfail="Got %d flow reports from DeepInsight (expect 1)" % (fiveTupleCount) |
| 68 | ) |
| 69 | |
| 70 | main.step("Clean up the test") |
| 71 | intTest.cleanUp(main) |
| 72 | |
| 73 | def CASE2 (self, main): |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 74 | main.case("Send a packet with invalid VLAN from one host to another host and check if DeepInsight receives drop reports") |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 75 | import time |
| 76 | import socket |
| 77 | from core import utilities |
| 78 | from tests.USECASE.SegmentRouting.INT.dependencies.IntTest import IntTest |
| 79 | main.cfgName = "CASE2" |
| 80 | |
| 81 | main.step("Setting up the test") |
| 82 | intTest = IntTest(scapy=True) |
| 83 | intTest.setUpTest(main) |
| 84 | |
| 85 | main.step("Setting up hosts and variables") |
| 86 | srcIfaceName = main.h1.interfaces[0]["name"] |
| 87 | dstIfaceName = main.h2.interfaces[0]["name"] |
| 88 | srcMac = main.h1.getMac(srcIfaceName) |
Yi Tseng | f34ec00 | 2022-02-28 15:56:44 -0800 | [diff] [blame] | 89 | dstMac = main.params.get("routerMac", "00:00:00:00:00:00") |
Yi Tseng | 69cdb17 | 2022-02-23 10:52:10 -0800 | [diff] [blame] | 90 | srcIp = main.h1.interfaces[0]['ips'][0] |
| 91 | dstIp = main.h2.interfaces[0]['ips'][0] |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 92 | srcPort = 2000 |
| 93 | dstPort = 8888 |
| 94 | |
| 95 | main.step("Sending a packet with invalid VLAN ID from h1") |
| 96 | startTimeMs = (time.time() - 5) * 1000 |
| 97 | pkt = """( |
| 98 | Ether(src="{}", dst="{}") / |
| 99 | Dot1Q(vlan=4093) / |
| 100 | IP(src="{}", dst="{}") / |
| 101 | UDP(sport={}, dport={}) / |
| 102 | ("A"*30) |
| 103 | )""".format(srcMac, dstMac, srcIp, dstIp, srcPort, dstPort) |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 104 | # Send multiple packets incase the server or DeepInsight drop the report accidently |
| 105 | # FIXME: Find the root cause, might be misconfiguration or Linux(e.g., rp_filter?) issue. |
| 106 | for _ in range(0, 5): |
| 107 | main.h1.sendPacket(iface=srcIfaceName, packet=pkt) |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 108 | endTimeMs = (time.time() + 5) * 1000 |
| 109 | |
| 110 | main.step("Checking drop report from DeepInsight") |
| 111 | def getDropAnomalies(*args, **kwargs): |
| 112 | return main.DeepInsight.getAnomalyRecords( |
| 113 | startTime=startTimeMs, |
| 114 | endTime=endTimeMs, |
| 115 | srcIp=srcIp, |
| 116 | dstIp=dstIp, |
| 117 | srcPort=srcPort, |
| 118 | dstPort=dstPort, |
| 119 | ipProto=socket.IPPROTO_UDP, |
| 120 | anomalyType="packet_drop", |
| 121 | ) |
| 122 | |
| 123 | # Need to wait few seconds until DeepInsight database updated. |
| 124 | dropAnomalies = utilities.retry( |
| 125 | f=getDropAnomalies, |
| 126 | retValue=[[]], |
| 127 | attempts=60, |
| 128 | ) |
| 129 | |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 130 | utilities.assert_lesser( |
| 131 | expect=0, actual=len(dropAnomalies), |
| 132 | onpass="Got %d drop anomaly from DeepInsight." % (len(dropAnomalies)), |
| 133 | onfail="Got no drop anomaly from DeepInsight." |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 134 | ) |
| 135 | |
| 136 | main.step("Checking drop reason from the report") |
Jon Hall | 1567b36 | 2021-12-10 10:23:10 -0800 | [diff] [blame] | 137 | try: |
| 138 | dropAnomaly = dropAnomalies[0] |
| 139 | dropReason = dropAnomaly["DropReason"] |
| 140 | except IndexError: |
| 141 | main.log.warn( "No drop report was found" ) |
| 142 | dropAnomaly = None |
| 143 | dropReason = None |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 144 | |
| 145 | # DROP_REASON_PORT_VLAN_MAPPING_MISS = 55 |
| 146 | utilities.assert_equals( |
| 147 | expect=55, actual=dropReason, |
| 148 | onpass="Got drop reason '55' as expected.", |
| 149 | onfail="Got drop reason '%d', expect '55'." % (dropReason) |
| 150 | ) |
| 151 | |
| 152 | main.step("Clean up the test") |
| 153 | intTest.cleanUp(main) |
| 154 | |
| 155 | def CASE3 (self, main): |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 156 | main.case("Send a packet with IP TTL value 1 from one host to another host and check if DeepInsight receives drop reports") |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 157 | import time |
| 158 | import socket |
| 159 | from core import utilities |
| 160 | from tests.USECASE.SegmentRouting.INT.dependencies.IntTest import IntTest |
| 161 | main.cfgName = "CASE3" |
| 162 | |
| 163 | main.step("Setting up the test") |
| 164 | intTest = IntTest(scapy=True) |
| 165 | intTest.setUpTest(main) |
| 166 | |
| 167 | main.step("Setting up hosts and variables") |
| 168 | srcIfaceName = main.h1.interfaces[0]["name"] |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 169 | srcMac = main.h1.getMac(srcIfaceName) |
| 170 | dstMac = main.params.get("routerMac", "00:00:00:00:00:00") |
Yi Tseng | 69cdb17 | 2022-02-23 10:52:10 -0800 | [diff] [blame] | 171 | srcIp = main.h1.interfaces[0]['ips'][0] |
| 172 | dstIp = main.h2.interfaces[0]['ips'][0] |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 173 | srcPort = 3000 |
| 174 | dstPort = 8888 |
| 175 | |
| 176 | main.step("Sending a packet with IP TTL value 1 from h1") |
| 177 | startTimeMs = (time.time() - 5) * 1000 |
| 178 | pkt = """( |
| 179 | Ether(src="{}", dst="{}") / |
| 180 | IP(src="{}", dst="{}", ttl=1) / |
| 181 | UDP(sport={}, dport={}) / |
| 182 | ("A"*30) |
| 183 | )""".format(srcMac, dstMac, srcIp, dstIp, srcPort, dstPort) |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 184 | # Send multiple packets incase the server or DeepInsight drop the report accidently |
| 185 | # FIXME: Find the root cause, might be misconfiguration or Linux(e.g., rp_filter?) issue. |
| 186 | for _ in range(0, 5): |
| 187 | main.h1.sendPacket(iface=srcIfaceName, packet=pkt) |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 188 | endTimeMs = (time.time() + 5) * 1000 |
| 189 | |
| 190 | main.step("Checking drop report from DeepInsight") |
| 191 | def getDropAnomalies(*args, **kwargs): |
| 192 | return main.DeepInsight.getAnomalyRecords( |
| 193 | startTime=startTimeMs, |
| 194 | endTime=endTimeMs, |
| 195 | srcIp=srcIp, |
| 196 | dstIp=dstIp, |
| 197 | srcPort=srcPort, |
| 198 | dstPort=dstPort, |
| 199 | ipProto=socket.IPPROTO_UDP, |
| 200 | anomalyType="packet_drop", |
| 201 | ) |
| 202 | |
| 203 | # Need to wait few seconds until DeepInsight database updated. |
| 204 | dropAnomalies = utilities.retry( |
| 205 | f=getDropAnomalies, |
| 206 | retValue=[[]], |
| 207 | attempts=60, |
| 208 | ) |
| 209 | |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 210 | utilities.assert_lesser( |
| 211 | expect=0, actual=len(dropAnomalies), |
| 212 | onpass="Got %d drop anomaly from DeepInsight." % (len(dropAnomalies)), |
| 213 | onfail="Got no drop anomaly from DeepInsight." |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 214 | ) |
| 215 | |
| 216 | main.step("Checking drop reason from report") |
Jon Hall | 1567b36 | 2021-12-10 10:23:10 -0800 | [diff] [blame] | 217 | try: |
| 218 | dropAnomaly = dropAnomalies[0] |
| 219 | dropReason = dropAnomaly["DropReason"] |
| 220 | except IndexError: |
| 221 | main.log.warn( "No drop report was found" ) |
| 222 | dropAnomaly = None |
| 223 | dropReason = None |
Yi Tseng | 0cb9b56 | 2021-09-22 17:13:58 -0700 | [diff] [blame] | 224 | # DROP_REASON_IP_TTL_ZERO = 26 |
| 225 | utilities.assert_equals( |
| 226 | expect=26, actual=dropReason, |
| 227 | onpass="Got drop reason '26' as expected.", |
| 228 | onfail="Got drop reason '%d', expect '26'." % (dropReason) |
| 229 | ) |
| 230 | |
| 231 | main.step("Clean up the test") |
| 232 | intTest.cleanUp(main) |
Yi Tseng | dda7e32 | 2021-09-20 14:21:20 -0700 | [diff] [blame] | 233 | |
| 234 | def CASE4(self, main): |
Yi Tseng | 2521bd4 | 2021-10-01 15:07:06 -0700 | [diff] [blame] | 235 | main.case("Generate traffic at high rate and expect queue congestion reports in DeepInsight") |
Yi Tseng | dda7e32 | 2021-09-20 14:21:20 -0700 | [diff] [blame] | 236 | from core import utilities |
| 237 | import time |
| 238 | from tests.USECASE.SegmentRouting.INT.dependencies.IntTest import IntTest |
| 239 | from tests.USECASE.SegmentRouting.dependencies.trex import Trex |
| 240 | main.cfgName = 'CASE4' |
| 241 | |
| 242 | main.step("Setting up the test") |
| 243 | intTest = IntTest(scapy=False) |
| 244 | intTest.setUpTest(main) |
| 245 | dstIp = main.params["TREX"]["flows"]["FLOW1"]["packet"]["ip_dst"] |
| 246 | |
| 247 | main.step("Set up TRex client") |
| 248 | trex = Trex() |
| 249 | trex.setup(main.TRexClient) |
| 250 | |
| 251 | # See SRpairedLeaves.param for the detail of each flow. |
| 252 | main.step("Reset queue report filter") |
| 253 | # Here we are using a low-latency(no congestion) traffic to reset the queue. |
| 254 | # report filter. |
| 255 | trex.createFlow("RESET_QUEUE_REPORT_FILTER") |
| 256 | trex.sendAndReceiveTraffic(5) |
| 257 | trex.resetFlows() |
| 258 | main.step("Generating traffic") |
| 259 | startTimeMs = (time.time() - 5) * 1000 |
| 260 | trex.createFlow("FLOW1") |
| 261 | trex.createFlow("FLOW2") |
| 262 | trex.sendAndReceiveTraffic(10) |
| 263 | endTimeMs = (time.time() + 5) * 1000 |
| 264 | |
| 265 | main.step("Checking queue report from DeepInsight") |
| 266 | def getQueueAnomaly(*args, **kwargs): |
| 267 | return main.DeepInsight.getAnomalyRecords( |
| 268 | startTime=startTimeMs, |
| 269 | endTime=endTimeMs, |
| 270 | dstIp=dstIp, |
| 271 | anomalyType="congested_flow", |
| 272 | ) |
| 273 | |
| 274 | # Need to wait few seconds until DeepInsight database updated. |
| 275 | queueAnomalies = utilities.retry( |
| 276 | f=getQueueAnomaly, |
| 277 | retValue=[[]], |
Yi Tseng | 69cdb17 | 2022-02-23 10:52:10 -0800 | [diff] [blame] | 278 | attempts=30, |
Yi Tseng | dda7e32 | 2021-09-20 14:21:20 -0700 | [diff] [blame] | 279 | ) |
| 280 | |
| 281 | # We should get at least two congestion records |
| 282 | utilities.assert_lesser( |
| 283 | expect=2, actual=len(queueAnomalies), |
| 284 | onpass="Got %d anomalies with 'congested_flow' type as expcted." % (len(queueAnomalies)), |
| 285 | onfail="Did not get any anomaly with 'congested_flow' type." |
| 286 | ) |
| 287 | |
| 288 | main.step("Clean up the test") |
| 289 | trex.teardown() |
| 290 | intTest.cleanUp(main) |