import os
-import time
import socket
+from socket import inet_pton, inet_ntop
import struct
+import time
from traceback import format_exc, format_stack
import scapy.compat
IPv6ExtHdrHopByHop
from util import ppp, ppc
from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ismaddr
-from scapy.utils import inet_pton, inet_ntop
class CaptureTimeoutError(Exception):
"""gso size on packet-generator interface"""
return self._gso_size
+ @property
+ def coalesce_is_enabled(self):
+ """coalesce enabled on packet-generator interface"""
+ if self._coalesce_enabled == 0:
+ return "coalesce-disabled"
+ return "coalesce-enabled"
+
@property
def out_path(self):
"""pcap file path - captured packets"""
"""CLI string to load the injected packets"""
if self._nb_replays is not None:
return "%s limit %d" % (self._input_cli, self._nb_replays)
+ if self._worker is not None:
+ return "%s worker %d" % (self._input_cli, self._worker)
return self._input_cli
@property
self._pg_index = pg_index
self._gso_enabled = gso
self._gso_size = gso_size
+ self._coalesce_enabled = 0
self._out_file = "pg%u_out.pcap" % self.pg_index
self._out_path = self.test.tempdir + "/" + self._out_file
self._in_file = "pg%u_in.pcap" % self.pg_index
of at most n packets.
If n < 0, this is no limit
"""
-
+ # disable the capture to flush the capture
+ self.disable_capture()
self._rename_previous_capture_file(self.out_path,
self.out_history_counter,
self._out_file)
def disable_capture(self):
self.test.vapi.cli("%s disable" % self.capture_cli)
- def add_stream(self, pkts, nb_replays=None):
+ def coalesce_enable(self):
+ """ Enable packet coalesce on this packet-generator interface"""
+ self._coalesce_enabled = 1
+ self.test.vapi.pg_interface_enable_disable_coalesce(self.sw_if_index,
+ 1)
+
+ def coalesce_disable(self):
+ """ Disable packet coalesce on this packet-generator interface"""
+ self._coalesce_enabled = 0
+ self.test.vapi.pg_interface_enable_disable_coalesce(self.sw_if_index,
+ 0)
+
+ def add_stream(self, pkts, nb_replays=None, worker=None):
"""
Add a stream of packets to this packet-generator
:param pkts: iterable packets
"""
+ self._worker = worker
self._nb_replays = nb_replays
self._rename_previous_capture_file(self.in_path,
self.in_history_counter,
raise AssertionError("Capture file present for interface %s" %
self.name)
+ def wait_for_pg_stop(self):
+ # wait till packet-generator is stopped
+ # "show packet-generator" while it is still running gives this:
+ # Name Enabled Count Parameters
+ # pcap0-sw_if_inde Yes 64 limit 64, ...
+ #
+ # also have a 5-minute timeout just in case things go terribly wrong...
+ deadline = time.time() + 300
+ while self.test.vapi.cli('show packet-generator').find("Yes") != -1:
+ self._test.sleep(0.01) # yield
+ if time.time() > deadline:
+ self.test.logger.debug("Timeout waiting for pg to stop")
+ break
+
def wait_for_capture_file(self, timeout=1):
"""
Wait until pcap capture file appears
:returns: True/False if the file is present or appears within timeout
"""
+ self.wait_for_pg_stop()
deadline = time.time() + timeout
if not os.path.isfile(self.out_path):
self.test.logger.debug("Waiting for capture file %s to appear, "
ARP(op=ARP.who_has, pdst=self.local_ip4,
psrc=self.remote_ip4, hwsrc=self.remote_mac))
- def create_ndp_req(self):
+ def create_ndp_req(self, addr=None):
"""Create NDP - NS applicable for this interface"""
- nsma = in6_getnsma(inet_pton(socket.AF_INET6, self.local_ip6))
+ if not addr:
+ addr = self.local_ip6
+ nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr))
d = inet_ntop(socket.AF_INET6, nsma)
return (Ether(dst=in6_getnsmac(nsma)) /
IPv6(dst=d, src=self.remote_ip6) /
- ICMPv6ND_NS(tgt=self.local_ip6) /
+ ICMPv6ND_NS(tgt=addr) /
ICMPv6NDOptSrcLLAddr(lladdr=self.remote_mac))
def resolve_arp(self, pg_interface=None):
ppp("Unexpected response to ARP request:", captured_packet))
raise
- def resolve_ndp(self, pg_interface=None, timeout=1):
+ def resolve_ndp(self, pg_interface=None, timeout=1, link_layer=False):
"""Resolve NDP using provided packet-generator interface
:param pg_interface: interface used to resolve, if None then this
interface is used
:param timeout: how long to wait for response before giving up
+ :param link_layer: resolve for global address if False (default)
+ or for link-layer address if True
"""
if pg_interface is None:
pg_interface = self
+ addr = self.local_ip6_ll if link_layer else self.local_ip6
self.test.logger.info("Sending NDP request for %s on port %s" %
- (self.local_ip6, pg_interface.name))
- ndp_req = self.create_ndp_req()
+ (addr, pg_interface.name))
+ ndp_req = self.create_ndp_req(addr)
pg_interface.add_stream(ndp_req)
pg_interface.enable_capture()
self.test.pg_start()