def Trigger(tc): if tc.skip: return api.types.status.SUCCESS result = api.types.status.SUCCESS for intf1 in tc.all_intfs: if result == api.types.status.FAILURE: break # Run tcpdump on intf1 in promiscuous mode req = api.Trigger_CreateExecuteCommandsRequest(serial=True) if api.GetNodeOs( tc.naples_node) == "windows" and intf1 in tc.host_intfs: intfGuid = ionic_utils.winIntfGuid(tc.naples_node, intf1) intfVal = str(ionic_utils.winTcpDumpIdx(tc.naples_node, intfGuid)) cmd = "/mnt/c/Windows/System32/tcpdump.exe" else: intfVal = intf1 cmd = "tcpdump" cmd += " -l -i " + intfVal + " -tne ether host " + tc.random_mac __PR_AddCommand(intf1, tc, req, cmd, True) # Run tcpdump in non-promiscuous mode on all other interfaces for intf2 in tc.all_intfs: if intf2 != intf1: if api.GetNodeOs(tc.naples_node ) == "windows" and intf2 in tc.host_intfs: intfGuid = ionic_utils.winIntfGuid(tc.naples_node, intf2) intfVal = str( ionic_utils.winTcpDumpIdx(tc.naples_node, intfGuid)) cmd = "/mnt/c/Windows/System32/tcpdump.exe" else: intfVal = intf2 cmd = "tcpdump" cmd += " -l -i " + intfVal + " -ptne ether host " + tc.random_mac __PR_AddCommand(intf2, tc, req, cmd, True) cmd = "sleep 1; ping -c 5 " + tc.target_IP + ";sleep 1" api.Trigger_AddHostCommand(req, tc.peer_node, cmd) cmds_terminated = False trig_resp = api.Trigger(req) # Verify packet filter flags of each interface in halctl show_lif_resp, ret = hal_show_utils.GetHALShowOutput( tc.naples_node, "lif") if not ret: api.Logger.error("Something went wrong with GetHALShowOutput") result = api.types.status.FAILURE break lif_obj_docs = yaml.load_all(show_lif_resp.commands[0].stdout, Loader=yaml.Loader) for lif_obj in lif_obj_docs: if lif_obj == None: break if api.GetNodeOs( tc.naples_node) == "windows" and intf1 in tc.host_intfs: halIntfName = ionic_utils.winHalIntfName(tc.naples_node, intf1) else: halIntfName = intf1 if lif_obj['spec']['name'].startswith(halIntfName): if lif_obj['spec']['packetfilter'][ 'receivepromiscuous'] != True: api.Logger.error( "halctl PR flag not set for promiscuous mode interface [%s]" % (intf1)) result = api.types.status.FAILURE else: if lif_obj['spec']['packetfilter'][ 'receivepromiscuous'] == True: api.Logger.error( "halctl PR flag set for non-promiscuous mode interface [%s]" % (lif_obj['spec']['name'])) result = api.types.status.FAILURE term_resp = api.Trigger_TerminateAllCommands(trig_resp) resp = api.Trigger_AggregateCommandsResponse(trig_resp, term_resp) cmds_terminated = True # Search tcpdump stdout for packets with dst MAC matching tc.random_mac pattern = "> " + tc.random_mac # Parse tcpdump stdout of promiscuous mode interface found = resp.commands[0].stdout.find(pattern) if tc.expect_pkt[intf1] and found == -1: api.Logger.error( "Interface [%s] did not receive Unknown Unicast packet in promiscuous mode" % (intf1)) api.PrintCommandResults(resp.commands[0]) result = api.types.status.FAILURE elif not tc.expect_pkt[intf1] and found > 0: api.Logger.error( "Interface [%s] received packet in promiscuous mode while not expecting" % (intf1)) api.PrintCommandResults(resp.commands[0]) result = api.types.status.FAILURE # Parse tcpdump stdout of rest of the interfaces cmds = resp.commands[1:] for cmd in cmds: found = cmd.stdout.find(pattern) if found > 0: api.Logger.error( "Interface in non-promiscuous mode received unknown unicast packet" ) api.PrintCommandResults(cmd) result = api.types.status.FAILURE break # api.Logger.info(" ================== DUMP FOR %s ================================================================" %(intf1)) # for cmd in resp.commands: # api.PrintCommandResults(cmd) # api.Logger.info(" ================== COMPLETED ITERATION FOR %s ====================================================" %(intf1)) if not cmds_terminated: api.Trigger_TerminateAllCommands(trig_resp) return result
def Trigger(tc): if tc.ignore == True: return api.types.status.SUCCESS if tc.error == True: return api.types.status.FAILURE tc.resp_tcpdump_erspan = None tc.resp_cleanup = None protoDir = api.GetTopologyDirectory() +\ "/gen/telemetry/{}/{}".format('mirror', 'endpoint') api.Logger.info("Template Config files location: ", protoDir) policies = utils.GetTargetJsons('mirror', 'endpoint') for policy_json in policies: # # Get template-Mirror Config # api.Logger.info("Adding one config object for {}", format(policy_json)) newObjects = agent_api.AddOneConfig(policy_json) if len(newObjects) == 0: api.Logger.error("Adding new objects to store failed") tc.error = True return api.types.status.FAILURE # # Modify template-Mirror Config to make sure that Naples-node # act as either source or destination # # Set up Collector in the remote node # if newObjects[0].kind == 'InterfaceMirrorSession': tc.ep_collector_objects = newObjects agent_api.RemoveConfigObjects(tc.ep_collector_objects) elif newObjects[0].kind == 'Endpoint': tc.endpoint_objects = newObjects agent_api.RemoveConfigObjects(tc.endpoint_objects) updateEndpointObjectTempl(tc, tc.endpoint_objects, tc.store_endpoint_objects[0]) for i in range(0, len(policies)): # # Push Collector object # if i == 0: colObjects = tc.ep_collector_objects if tc.iterators.session == 'single': ret = eutils.generateEpCollectorConfig(tc, colObjects) else: ret = eutils.generateEpCollectorConfigForMultiMirrorSession( tc, colObjects) if ret != api.types.status.SUCCESS: api.Logger.error("Unable to identify Collector Workload") tc.error = True return api.types.status.FAILURE api.Logger.info("Pushing collector objects") ret = agent_api.PushConfigObjects(colObjects, [tc.naples.node_name], [tc.naples_device_name]) if ret != api.types.status.SUCCESS: api.Logger.error("Unable to push collector objects") tc.error = True return api.types.status.FAILURE continue api.Logger.info("Generating Endpoint objects") cfg_api.PrintConfigsObjects(colObjects) # # Update Endpoint objects # epObjects = tc.endpoint_objects ret = eutils.generateEndpointConfig(tc, epObjects, colObjects) if ret != api.types.status.SUCCESS: agent_api.DeleteConfigObjects(tc.ep_collector_objects, [tc.naples.node_name], [tc.naples_device_name]) api.Logger.error("Unable to identify Endpoints") tc.error = True return api.types.status.FAILURE api.Logger.info("Pushing Endpoint objects") ret = agent_api.UpdateConfigObjects(epObjects, [tc.naples.node_name], [tc.naples_device_name]) if ret != api.types.status.SUCCESS: agent_api.DeleteConfigObjects(tc.ep_collector_objects, [tc.naples.node_name], [tc.naples_device_name]) api.Logger.error("Unable to update endpoint objects") tc.error = True return api.types.status.FAILURE # # Establish Forwarding set up between Naples-peer and Collectors # eutils.establishForwardingSetup(tc) req_tcpdump_erspan = api.Trigger_CreateExecuteCommandsRequest(\ serial = True) for c in range(0, len(tc.ep_collector)): # # Set up TCPDUMP's on the collector # idx = tc.ep_collector_idx[c] if tc.ep_collector[c].IsNaples(): ### TODO - run & revisit for windows case and fix any issues. if api.GetNodeOs(tc.naples.node_name) == "windows": intfGuid = ionic_utils.winIntfGuid( tc.ep_collector[c].node_name, tc.ep_collector[c].interface) intfVal = str( ionic_utils.winTcpDumpIdx(tc.ep_collector[c].node_name, intfGuid)) cmd = "sudo /mnt/c/Windows/System32/tcpdump.exe -c 1000 -XX -vv -i {} ip proto 47 and dst {} -U -w ep-mirror-{}.pcap"\ .format(intfVal, tc.collector_ip_address[idx], c) else: intfVal = tc.ep_collector[c].interface cmd = "tcpdump -c 1000 -XX -vv -nni {} ip proto gre and dst {}\ --immediate-mode -U -w ep-mirror-{}.pcap"\ .format(intfVal, tc.collector_ip_address[idx], c) else: cmd = "tcpdump -p -c 1000 -XX -vv -nni {} ip proto gre\ and dst {} --immediate-mode -U -w ep-mirror-{}.pcap"\ .format(tc.ep_collector[c].interface, tc.collector_ip_address[idx], c) eutils.add_command(req_tcpdump_erspan, tc.ep_collector[c], cmd, True) resp_tcpdump_erspan = api.Trigger(req_tcpdump_erspan) for cmd in resp_tcpdump_erspan.commands: api.PrintCommandResults(cmd) # # Classic mode requires a delay to make sure that TCPDUMP background # process is fully up # if tc.classic_mode == True: time.sleep(2) # # Trigger packets for ERSPAN to take effect # tc.dest_port = '120' if api.GetNodeOs(tc.naples.node_name) == 'linux' or api.GetNodeOs( tc.naples.node_name) == 'windows': eutils.triggerTrafficInClassicModeLinux(tc) else: eutils.triggerTrafficInHostPinModeOrFreeBSD(tc) # # Dump sessions/flows/P4-tables for debug purposes # eutils.showSessionAndP4TablesForDebug(tc, tc.ep_collector, tc.ep_collector_idx) # # Terminate TCPDUMP background process # term_resp_tcpdump_erspan = api.Trigger_TerminateAllCommands(\ resp_tcpdump_erspan) tc.resp_tcpdump_erspan = api.Trigger_AggregateCommandsResponse(\ resp_tcpdump_erspan, term_resp_tcpdump_erspan) if api.GetNodeOs(tc.naples.node_name) == "windows": req = api.Trigger_CreateExecuteCommandsRequest(serial=True) cmd = api.WINDOWS_POWERSHELL_CMD + " Stop-Process -Name 'tcpdump' -Force" api.Trigger_AddCommand(req, tc.naples.node_name, tc.naples.workload_name, cmd, background=False) resp = api.Trigger(req) # Delete the objects eutils.deGenerateEndpointConfig(tc, tc.endpoint_objects, tc.ep_collector_objects) agent_api.UpdateConfigObjects(tc.endpoint_objects, [tc.naples.node_name], [tc.naples_device_name]) agent_api.DeleteConfigObjects(tc.ep_collector_objects, [tc.naples.node_name], [tc.naples_device_name]) # # Make sure that Mirror-config has been removed # tc.resp_cleanup = eutils.showP4TablesForValidation(tc) return api.types.status.SUCCESS
def Trigger(tc): if tc.skip: return api.types.status.SUCCESS result = api.types.status.SUCCESS if tc.args.mode == "non-promiscuous": # Run tcdpump in non-promiscuous mode tcpdump_flags_extra = " -p " else: tcpdump_flags_extra = "" # For further debug, listen for packets on peer node as well if tc.args.mode == "promiscuous": req_node2 = api.Trigger_CreateExecuteCommandsRequest(serial=True) for workload in tc.peer_workloads: if api.GetNodeOs(tc.naples_node) == "windows": intfGuid = ionic_utils.winIntfGuid(tc.naples_node, workload.interface) intf = str(ionic_utils.winTcpDumpIdx(tc.naples_node, intfGuid)) cmd = "/mnt/c/Windows/System32/tcpdump.exe" else: intf = workload.interface cmd = "tcpdump" cmd += " -l -i " + intf + " -tne arp host " + tc.target_IP + " or icmp" api.Trigger_AddHostCommand(req_node2, tc.peer_node, cmd, True) trig_resp_node2 = api.Trigger(req_node2) for intf1 in tc.host_intfs: if result == api.types.status.FAILURE: break # Create a static ARP entry for the target IP with MAC addr belonging to current host interface mac_addr = host_utils.GetMACAddress(tc.naples_node, intf1) api.Logger.info("%s MAC ADDR: %s" % (intf1, mac_addr)) if host_utils.AddStaticARP( tc.peer_node, tc.peer_workloads[0].interface, tc.target_IP, mac_addr) != api.types.status.SUCCESS: api.Logger.error("Failed to add Static ARP entry on %s %s %s" % (tc.peer_node, tc.target_IP, mac_addr)) result = api.types.status.FAILURE break req = api.Trigger_CreateExecuteCommandsRequest(serial=True) # Warm N3K FDB table with current interface MAC address (to avoid future flooding of packets with DST MAC matching this interface) if api.GetNodeOs(tc.naples_node) == "windows": cmd = "/mnt/c/Windows/System32/arp-ping.exe -n 1 -s " + utils.GetIPAddress( tc.naples_node, intf1) + " " + tc.target_IP else: cmd = "arping -c 1 -I " + intf1 + " " + tc.target_IP api.Trigger_AddHostCommand(req, tc.naples_node, cmd) # Run tcpdump on all interfaces for intf2 in tc.all_intfs: if api.GetNodeOs( tc.naples_node) == "windows" and intf2 in tc.host_intfs: intfGuid = ionic_utils.winIntfGuid(tc.naples_node, intf2) intfVal = str( ionic_utils.winTcpDumpIdx(tc.naples_node, intfGuid)) cmd = "/mnt/c/Windows/System32/tcpdump.exe" else: intfVal = intf2 cmd = "tcpdump" cmd += " -l -i " + intfVal + tcpdump_flags_extra + " -tne ether host " + mac_addr __PR_AddCommand(intf2, tc, req, cmd, True) cmd = "sleep 1; ping -c 5 " + tc.target_IP + ";sleep 1" api.Trigger_AddHostCommand(req, tc.peer_node, cmd) trig_resp = api.Trigger(req) term_resp = api.Trigger_TerminateAllCommands(trig_resp) resp = api.Trigger_AggregateCommandsResponse(trig_resp, term_resp) # Skipping halctl flag checks here as other testcases prior to this already validates halcltl o/p. # Search tcpdump stdout for packets with dst MAC matching mac_addr # No other interface other than current 'intf1' should receive the packet pattern = "> " + mac_addr cmds = resp.commands[1:-1] for intf, cmd in zip(tc.all_intfs, cmds): found = cmd.stdout.find(pattern) if intf == intf1: if found == -1: api.Logger.error( "Interface [%s] did not receive expected known unicast packet" % (intf)) result = api.types.status.FAILURE elif found > 0: api.Logger.error( "Interface [%s] received known unicast packet while not expecting" % (intf)) result = api.types.status.FAILURE # Cleanup for current host interface 'intf1' if host_utils.DeleteARP(tc.peer_node, tc.peer_workloads[0].interface, tc.target_IP) != api.types.status.SUCCESS: api.Logger.error("Failed to delete Static ARP entry on %s %s" % (tc.peer_node, tc.target_IP)) result = api.types.status.FAILURE if tc.args.mode == "promiscuous": term_resp_node2 = api.Trigger_TerminateAllCommands(trig_resp_node2) resp_node2 = api.Trigger_AggregateCommandsResponse( trig_resp_node2, term_resp_node2) # Incase of testcase failure, dump the entire command output for further debug if result == api.types.status.FAILURE: api.Logger.error( " ============================= COMMAND DUMP ================================================" ) for cmd in resp.commands: api.PrintCommandResults(cmd) # Dump tcpdump o/p from peer node if tc.args.mode == "promiscuous": api.Logger.error( " ============================= COMMAND DUMP from NODE 2 ================================================" ) for cmd in resp_node2.commands: api.PrintCommandResults(cmd) api.Logger.error( " ============================= END NODE 2 DUMP ========================================================" ) return result
def Trigger(tc): if tc.skip: return api.types.status.SUCCESS result = api.types.status.SUCCESS req = api.Trigger_CreateExecuteCommandsRequest(serial=True) if tc.args.mode == "non-promiscuous": # Run tcdpump in non-promiscuous mode tcpdump_flags_extra = " -p " else: tcpdump_flags_extra = "" # Run tcpdump on all interfaces for intf in tc.all_intfs: if api.GetNodeOs( tc.naples_node) == "windows" and intf in tc.host_intfs: intfGuid = ionic_utils.winIntfGuid(tc.naples_node, intf) intfVal = str(ionic_utils.winTcpDumpIdx(tc.naples_node, intfGuid)) cmd = "/mnt/c/Windows/System32/tcpdump.exe" else: intfVal = intf cmd = "tcpdump" cmd += " -l -i " + intfVal + tcpdump_flags_extra + " -tne ether host " + tc.random_mac __PR_AddCommand(intf, tc, req, cmd, True) cmd = "sleep 1; ping -c 5 " + tc.target_IP + ";sleep 1" api.Trigger_AddHostCommand(req, tc.peer_node, cmd) trig_resp = api.Trigger(req) # Verify packet filter flags of each interface in halctl show_lif_resp, ret = hal_show_utils.GetHALShowOutput(tc.naples_node, "lif") if not ret: api.Logger.error("Something went wrong with GetHALShowOutput") result = api.types.status.FAILURE lif_obj_docs = yaml.load_all(show_lif_resp.commands[0].stdout) for lif_obj in lif_obj_docs: if lif_obj == None: break # See if the lif belongs to any of the interface in tc.all_intfs (inteface lif) intf_lif = False for intf in tc.all_intfs: if api.GetNodeOs( tc.naples_node) == "windows" and intf in tc.host_intfs: halIntfName = ionic_utils.winHalIntfName(tc.naples_node, intf) else: halIntfName = intf if lif_obj['spec']['name'].startswith(halIntfName): intf_lif = True break lif_pr_flag = lif_obj['spec']['packetfilter']['receivepromiscuous'] # A lif must have its PR flag when it is an interface lif and tc.args.mode is 'promiscuous' if tc.args.mode == "promiscuous": if intf_lif and lif_pr_flag != True: api.Logger.error( "halctl PR flag not set for promiscuous mode interface [%s]" % (lif_obj['spec']['name'])) result = api.types.status.FAILURE else: if lif_pr_flag == True: api.Logger.error( "halctl PR flag set for non-promiscuous mode LIF [%s]" % (lif_obj['spec']['name'])) result = api.types.status.FAILURE term_resp = api.Trigger_TerminateAllCommands(trig_resp) resp = api.Trigger_AggregateCommandsResponse(trig_resp, term_resp) # Search tcpdump stdout for packets with dst MAC matching tc.random_mac pattern = "> " + tc.random_mac cmds = resp.commands[:-1] for intf, cmd in zip(tc.all_intfs, cmds): found = cmd.stdout.find(pattern) if found > 0 and not tc.expect_pkt[intf]: api.Logger.error( "Interface [%s] received Unknown unicast packet while not expecting" % (intf)) result = api.types.status.FAILURE elif found == -1 and tc.expect_pkt[intf]: api.Logger.error( "Interface [%s] did not receive expected Unknown unicast packet" % (intf)) result = api.types.status.FAILURE # Incase of testcase failure, dump the entire command output for further debug if result == api.types.status.FAILURE: api.Logger.error( " ============================= COMMAND DUMP ================================================" ) for cmd in resp.commands: api.PrintCommandResults(cmd) api.Logger.error( " ============================= END ========================================================" ) return result