summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>2018-12-20 17:25:49 +1300
committerDouglas Bagnall <dbagnall@samba.org>2019-01-08 23:55:33 +0100
commit7edf58dc58630eca4f9b11242035aa5d6d24e285 (patch)
treeafe6d97036a784f2c21f1b9413b7a273629d9502 /python
parent273eb3dffbaff02b9cc4246783153e26d68485c5 (diff)
downloadsamba-7edf58dc58630eca4f9b11242035aa5d6d24e285.tar.gz
traffic: new version of model with packet_rate, version number
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'python')
-rw-r--r--python/samba/emulate/traffic.py118
-rw-r--r--python/samba/tests/blackbox/testdata/traffic-sample-very-short.model11
-rw-r--r--python/samba/tests/blackbox/testdata/traffic_learner.expected45
-rw-r--r--python/samba/tests/blackbox/testdata/traffic_replay-0.expected18
-rw-r--r--python/samba/tests/blackbox/testdata/traffic_replay-1.expected19
-rw-r--r--python/samba/tests/blackbox/testdata/traffic_replay.expected28
-rw-r--r--python/samba/tests/blackbox/traffic_learner.py2
-rw-r--r--python/samba/tests/blackbox/traffic_replay.py55
8 files changed, 202 insertions, 94 deletions
diff --git a/python/samba/emulate/traffic.py b/python/samba/emulate/traffic.py
index b6097cdc120..807fa8244e2 100644
--- a/python/samba/emulate/traffic.py
+++ b/python/samba/emulate/traffic.py
@@ -54,6 +54,8 @@ from samba.compat import get_string
from samba.logger import get_samba_logger
import bisect
+CURRENT_MODEL_VERSION = 2 # save as this
+REQUIRED_MODEL_VERSION = 2 # load accepts this or greater
SLEEP_OVERHEAD = 3e-4
# we don't use None, because it complicates [de]serialisation
@@ -1136,7 +1138,7 @@ class TrafficModel(object):
self.n = n
self.dns_opcounts = defaultdict(int)
self.cumulative_duration = 0.0
- self.conversation_rate = [0, 1]
+ self.packet_rate = [0, 1]
def learn(self, conversations, dns_opcounts={}):
prev = 0.0
@@ -1149,10 +1151,15 @@ class TrafficModel(object):
self.dns_opcounts[k] += v
if len(conversations) > 1:
- elapsed =\
- conversations[-1].start_time - conversations[0].start_time
- self.conversation_rate[0] = len(conversations)
- self.conversation_rate[1] = elapsed
+ first = conversations[0].start_time
+ total = 0
+ last = first + 0.1
+ for c in conversations:
+ total += len(c)
+ last = max(last, c.packets[-1].timestamp)
+
+ self.packet_rate[0] = total
+ self.packet_rate[1] = last - first
for c in conversations:
client, server = c.guess_client_server(server)
@@ -1196,7 +1203,8 @@ class TrafficModel(object):
'ngrams': ngrams,
'query_details': query_details,
'cumulative_duration': self.cumulative_duration,
- 'conversation_rate': self.conversation_rate,
+ 'packet_rate': self.packet_rate,
+ 'version': CURRENT_MODEL_VERSION
}
d['dns'] = self.dns_opcounts
@@ -1211,6 +1219,17 @@ class TrafficModel(object):
d = json.load(f)
+ try:
+ version = d["version"]
+ if version < REQUIRED_MODEL_VERSION:
+ raise ValueError("the model file is version %d; "
+ "version %d is required" %
+ (version, REQUIRED_MODEL_VERSION))
+ except KeyError:
+ raise ValueError("the model file lacks a version number; "
+ "version %d is required" %
+ (REQUIRED_MODEL_VERSION))
+
for k, v in d['ngrams'].items():
k = tuple(str(k).split('\t'))
values = self.ngrams.setdefault(k, [])
@@ -1232,18 +1251,22 @@ class TrafficModel(object):
self.dns_opcounts[k] += v
self.cumulative_duration = d['cumulative_duration']
- self.conversation_rate = d['conversation_rate']
-
- def construct_conversation(self, timestamp=0.0, client=2, server=1,
- hard_stop=None, replay_speed=1):
- """Construct a individual converation from the model."""
-
- c = Conversation(timestamp, (server, client), conversation_id=client)
-
+ self.packet_rate = d['packet_rate']
+
+ def construct_conversation_sequence(self, timestamp=0.0,
+ hard_stop=None,
+ replay_speed=1,
+ ignore_before=0):
+ """Construct an individual conversation packet sequence from the
+ model.
+ """
+ c = []
key = (NON_PACKET,) * (self.n - 1)
+ if ignore_before is None:
+ ignore_before = timestamp - 1
- while key in self.ngrams:
- p = random.choice(self.ngrams.get(key, NON_PACKET))
+ while True:
+ p = random.choice(self.ngrams.get(key, (NON_PACKET,)))
if p == NON_PACKET:
break
@@ -1263,47 +1286,50 @@ class TrafficModel(object):
timestamp += wait
if hard_stop is not None and timestamp > hard_stop:
break
- c.add_short_packet(timestamp, protocol, opcode, extra)
+ if timestamp >= ignore_before:
+ c.append((timestamp, protocol, opcode, extra))
key = key[1:] + (p,)
return c
- def generate_conversations(self, rate, duration, replay_speed=1):
+ def generate_conversations(self, scale, duration, replay_speed=1,
+ server=1, client=2):
"""Generate a list of conversations from the model."""
- # We run the simulation for at least ten times as long as our
- # desired duration, and take a section near the start.
- rate_n, rate_t = self.conversation_rate
+ # We run the simulation for ten times as long as our desired
+ # duration, and take the section at the end.
+ lead_in = 9 * duration
+ rate_n, rate_t = self.packet_rate
+ target_packets = int(duration * scale * rate_n / rate_t)
- duration2 = max(rate_t, duration * 2)
- n = rate * duration2 * rate_n / rate_t
+ conversations = []
+ n_packets = 0
+
+ while n_packets < target_packets:
+ start = random.uniform(-lead_in, duration)
+ c = self.construct_conversation_sequence(start,
+ hard_stop=duration,
+ replay_speed=replay_speed,
+ ignore_before=0)
+ conversations.append(c)
+ n_packets += len(c)
+
+ print(("we have %d packets (target %d) in %d conversations at scale %f"
+ % (n_packets, target_packets, len(conversations), scale)),
+ file=sys.stderr)
+ conversations.sort() # sorts by first element == start time
+ return seq_to_conversations(conversations)
- server = 1
- client = 2
- conversations = []
- end = duration2
- start = end - duration
-
- while client < n + 2:
- start = random.uniform(0, duration2)
- c = self.construct_conversation(start,
- client,
- server,
- hard_stop=(duration2 * 5),
- replay_speed=replay_speed)
-
- c.forget_packets_outside_window(start, end)
- c.renormalise_times(start)
- if len(c) != 0:
- conversations.append(c)
+def seq_to_conversations(seq, server=1, client=2):
+ conversations = []
+ for s in seq:
+ if s:
+ c = Conversation(s[0][0], (server, client), s)
client += 1
-
- print(("we have %d conversations at rate %f" %
- (len(conversations), rate)), file=sys.stderr)
- conversations.sort()
- return conversations
+ conversations.append(c)
+ return conversations
IP_PROTOCOLS = {
diff --git a/python/samba/tests/blackbox/testdata/traffic-sample-very-short.model b/python/samba/tests/blackbox/testdata/traffic-sample-very-short.model
index 8e299eb19e1..0de93ed1c8d 100644
--- a/python/samba/tests/blackbox/testdata/traffic-sample-very-short.model
+++ b/python/samba/tests/blackbox/testdata/traffic-sample-very-short.model
@@ -30,14 +30,14 @@
"-": 1
}
},
- "conversation_rate": [
- 2,
- 0.12712717056274414
- ],
"dns": {
"1": 9,
"0": 9
},
+ "packet_rate": [
+ 50,
+ 0.32482
+ ],
"query_details": {
"rpc_netlogon:29": {
"-": 1
@@ -56,5 +56,6 @@
"": 1
}
},
- "cumulative_duration": 0.39243292808532715
+ "cumulative_duration": 0.39243292808532715,
+ "version": 2
} \ No newline at end of file
diff --git a/python/samba/tests/blackbox/testdata/traffic_learner.expected b/python/samba/tests/blackbox/testdata/traffic_learner.expected
index 8e299eb19e1..3ae80899caf 100644
--- a/python/samba/tests/blackbox/testdata/traffic_learner.expected
+++ b/python/samba/tests/blackbox/testdata/traffic_learner.expected
@@ -1,4 +1,26 @@
{
+ "packet_rate": [
+ 10,
+ 0.22707200050354004
+ ],
+ "query_details": {
+ "rpc_netlogon:29": {
+ "-": 1
+ },
+ "cldap:3": {
+ "\t\t\tNetlogon\t\t\t": 3
+ },
+ "ldap:3": {
+ "\t\t\tsubschemaSubentry,dsServiceName,namingContexts,defaultNamingContext,schemaNamingContext,configurationNamingContext,rootDomainNamingContext,supportedControl,supportedLDAPVersion,supportedLDAPPolicies,supportedSASLMechanisms,dnsHostName,ldapServiceName,serverName,supportedCapabilities\t\t\t": 1,
+ "2\tDC,DC\t\tcn\t\t\t": 1
+ },
+ "ldap:2": {
+ "\t\t\t\t\t\t": 1
+ },
+ "kerberos:": {
+ "": 1
+ }
+ },
"ngrams": {
"-\t-": {
"cldap:3": 1,
@@ -30,31 +52,10 @@
"-": 1
}
},
- "conversation_rate": [
- 2,
- 0.12712717056274414
- ],
+ "version": 2,
"dns": {
"1": 9,
"0": 9
},
- "query_details": {
- "rpc_netlogon:29": {
- "-": 1
- },
- "cldap:3": {
- "\t\t\tNetlogon\t\t\t": 3
- },
- "ldap:3": {
- "\t\t\tsubschemaSubentry,dsServiceName,namingContexts,defaultNamingContext,schemaNamingContext,configurationNamingContext,rootDomainNamingContext,supportedControl,supportedLDAPVersion,supportedLDAPPolicies,supportedSASLMechanisms,dnsHostName,ldapServiceName,serverName,supportedCapabilities\t\t\t": 1,
- "2\tDC,DC\t\tcn\t\t\t": 1
- },
- "ldap:2": {
- "\t\t\t\t\t\t": 1
- },
- "kerberos:": {
- "": 1
- }
- },
"cumulative_duration": 0.39243292808532715
} \ No newline at end of file
diff --git a/python/samba/tests/blackbox/testdata/traffic_replay-0.expected b/python/samba/tests/blackbox/testdata/traffic_replay-0.expected
new file mode 100644
index 00000000000..8f44438ef97
--- /dev/null
+++ b/python/samba/tests/blackbox/testdata/traffic_replay-0.expected
@@ -0,0 +1,18 @@
+0.011388 06 2 1 ldap 3 searchRequest 2 DC,DC cn
+0.221447 06 2 1 ldap 2 unbindRequest
+0.460878 06 3 1 ldap 3 searchRequest 2 DC,DC cn
+0.581933 11 4 1 cldap 3 searchRequest Netlogon
+0.596977 11 4 1 cldap 3 searchRequest Netlogon
+0.611184 11 4 1 cldap 3 searchRequest Netlogon
+0.666808 06 3 1 ldap 2 unbindRequest
+0.744297 06 4 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.768994 06 4 1 kerberos
+0.772476 06 4 1 ldap 3 searchRequest 2 DC,DC cn
+0.805442 11 5 1 cldap 3 searchRequest Netlogon
+0.805536 11 5 1 cldap 3 searchRequest Netlogon
+0.807659 11 5 1 cldap 3 searchRequest Netlogon
+0.808614 11 5 1 cldap 3 searchRequest Netlogon
+0.808819 11 5 1 cldap 3 searchRequest Netlogon
+0.865384 06 6 1 ldap 3 searchRequest subschemaSubentry,dsServiceName,namingContexts,defaultNamingContext,schemaNamingContext,configurationNamingContext,rootDomainNamingContext,supportedControl,supportedLDAPVersion,supportedLDAPPolicies,supportedSASLMechanisms,dnsHostName,ldapServiceName,serverName,supportedCapabilities
+0.973595 06 5 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.974012 06 5 1 kerberos
diff --git a/python/samba/tests/blackbox/testdata/traffic_replay-1.expected b/python/samba/tests/blackbox/testdata/traffic_replay-1.expected
new file mode 100644
index 00000000000..1ac696819bd
--- /dev/null
+++ b/python/samba/tests/blackbox/testdata/traffic_replay-1.expected
@@ -0,0 +1,19 @@
+0.011519 11 2 1 cldap 3 searchRequest Netlogon
+0.012916 11 2 1 cldap 3 searchRequest Netlogon
+0.158388 06 3 1 ldap 3 searchRequest 2 DC,DC cn
+0.164506 06 2 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.166151 06 2 1 kerberos
+0.166301 06 2 1 ldap 3 searchRequest subschemaSubentry,dsServiceName,namingContexts,defaultNamingContext,schemaNamingContext,configurationNamingContext,rootDomainNamingContext,supportedControl,supportedLDAPVersion,supportedLDAPPolicies,supportedSASLMechanisms,dnsHostName,ldapServiceName,serverName,supportedCapabilities
+0.258932 06 4 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.259908 06 4 1 kerberos
+0.260073 06 4 1 ldap 3 searchRequest 2 DC,DC cn
+0.286044 06 5 1 ldap 3 searchRequest 2 DC,DC cn
+0.295757 06 3 1 ldap 2 unbindRequest
+0.459791 06 5 1 ldap 2 unbindRequest
+0.553887 06 6 1 ldap 3 searchRequest subschemaSubentry,dsServiceName,namingContexts,defaultNamingContext,schemaNamingContext,configurationNamingContext,rootDomainNamingContext,supportedControl,supportedLDAPVersion,supportedLDAPPolicies,supportedSASLMechanisms,dnsHostName,ldapServiceName,serverName,supportedCapabilities
+0.641127 11 7 1 cldap 3 searchRequest Netlogon
+0.641297 11 7 1 cldap 3 searchRequest Netlogon
+0.783989 06 6 1 ldap 2 unbindRequest
+0.901096 06 7 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.915260 06 7 1 kerberos
+0.915711 06 7 1 ldap 3 searchRequest 2 DC,DC cn
diff --git a/python/samba/tests/blackbox/testdata/traffic_replay.expected b/python/samba/tests/blackbox/testdata/traffic_replay.expected
index b29c8b04121..0c6b2a2fe52 100644
--- a/python/samba/tests/blackbox/testdata/traffic_replay.expected
+++ b/python/samba/tests/blackbox/testdata/traffic_replay.expected
@@ -1,10 +1,18 @@
-0.000000 06 3 5 1 ldap 3 searchRequest 2 DC,DC cn
-0.127127 11 6 1 cldap 3 searchRequest Netlogon
-0.127391 11 6 1 cldap 3 searchRequest Netlogon
-0.127689 11 6 1 cldap 3 searchRequest Netlogon
-0.227072 06 3 5 1 ldap 2 unbindRequest
-0.282995 06 16 6 1 rpc_netlogon 29 NetrLogonGetDomainInfo
-0.287553 06 18 6 1 kerberos
-0.287759 06 16 1 6 rpc_netlogon 29 NetrLogonGetDomainInfo
-0.291161 06 19 6 1 ldap 3 searchRequest subschemaSubentry,dsServiceName,namingContexts,defaultNamingContext,schemaNamingContext,configurationNamingContext,rootDomainNamingContext,supportedControl,supportedLDAPVersion,supportedLDAPPolicies,supportedSASLMechanisms,dnsHostName,ldapServiceName,serverName,supportedCapabilities
-0.292488 06 18 1 6 kerberos
+0.040433 06 2 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.059203 06 2 1 kerberos
+0.061641 06 2 1 ldap 3 searchRequest 2 DC,DC cn
+0.535074 11 3 1 cldap 3 searchRequest Netlogon
+0.535369 11 3 1 cldap 3 searchRequest Netlogon
+0.536671 11 3 1 cldap 3 searchRequest Netlogon
+0.537238 11 3 1 cldap 3 searchRequest Netlogon
+0.537362 11 3 1 cldap 3 searchRequest Netlogon
+0.602824 11 4 1 cldap 3 searchRequest Netlogon
+0.640115 11 4 1 cldap 3 searchRequest Netlogon
+0.714546 06 3 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.715865 06 3 1 kerberos
+0.716613 06 3 1 ldap 3 searchRequest 2 DC,DC cn
+0.767674 06 4 1 rpc_netlogon 29 NetrLogonGetDomainInfo
+0.778022 06 5 1 ldap 3 searchRequest 2 DC,DC cn
+0.792356 06 4 1 kerberos
+0.792763 06 4 1 ldap 3 searchRequest 2 DC,DC cn
+0.960412 06 5 1 ldap 2 unbindRequest
diff --git a/python/samba/tests/blackbox/traffic_learner.py b/python/samba/tests/blackbox/traffic_learner.py
index dd7c7c15678..e6adce7a568 100644
--- a/python/samba/tests/blackbox/traffic_learner.py
+++ b/python/samba/tests/blackbox/traffic_learner.py
@@ -75,4 +75,4 @@ class TrafficLearnerTests(BlackboxTestCase):
expected_details = {k: sorted(v) for k, v in expected.query_details.items()}
self.assertEquals(expected_details, actual_details)
self.assertEquals(expected.cumulative_duration, actual.cumulative_duration)
- self.assertEquals(expected.conversation_rate, actual.conversation_rate)
+ self.assertEquals(expected.packet_rate, actual.packet_rate)
diff --git a/python/samba/tests/blackbox/traffic_replay.py b/python/samba/tests/blackbox/traffic_replay.py
index 015db2ed39b..a84d1a423e4 100644
--- a/python/samba/tests/blackbox/traffic_replay.py
+++ b/python/samba/tests/blackbox/traffic_replay.py
@@ -25,12 +25,13 @@ from samba.tests import BlackboxTestCase
DATA_DIR = "python/samba/tests/blackbox/testdata"
SCRIPT = "script/traffic_replay"
-FIXED = "--fixed-password trafficreplay01%"
+FIXED = "--fixed-password=trafficreplay01%"
SERVER = os.environ["SERVER"]
PASSWORD = os.environ["PASSWORD"]
USER = os.environ["USERNAME"]
-STD_OPTIONS = "-U%s%%%s %s" % (USER, PASSWORD, SERVER)
-EXPECTED_NAME = os.path.join(DATA_DIR, "traffic_replay.expected")
+CREDS = "-U%s%%%s" % (USER, PASSWORD)
+MODEL = os.path.join(DATA_DIR, "traffic-sample-very-short.model")
+EXPECTED_OUTPUT = os.path.join(DATA_DIR, "traffic_replay-%s.expected")
@contextmanager
@@ -49,7 +50,7 @@ class TrafficLearnerTests(BlackboxTestCase):
def tearDown(self):
options = "--clean-up"
- command = "%s %s %s" % (SCRIPT, options, STD_OPTIONS)
+ command = "%s %s %s %s" % (SCRIPT, options, CREDS, SERVER)
self.check_run(command)
def test_generate_users_only(self):
@@ -57,16 +58,48 @@ class TrafficLearnerTests(BlackboxTestCase):
"""
options = ("--generate-users-only --number-of-users 20 "
"--number-of-groups 5 --average-groups-per-user 2")
- command = "%s %s %s %s" % (
- SCRIPT, options, FIXED, STD_OPTIONS)
+ command = "%s %s %s %s %s" % (
+ SCRIPT, options, FIXED, CREDS, SERVER)
self.check_run(command)
+ command = "%s %s %s %s %s %s" % (
+ SCRIPT, MODEL, options, FIXED, CREDS, SERVER)
+ self.check_run(command)
+
+ def test_summary_generation(self):
+ """Ensure a summary file is generated and the contents are correct"""
+
+ for i, opts in enumerate((["--random-seed=3"],
+ ["--random-seed=4"],
+ ["--random-seed=3",
+ "--conversation-persistence=0.5"],
+ ["--random-seed=3",
+ "--old-scale",
+ "--conversation-persistence=0.95"],
+ )):
+ with temp_file(self.tempdir) as output:
+ command = ([SCRIPT, MODEL,
+ "--traffic-summary", output,
+ "-D1", "-S0.1"] +
+ opts +
+ [FIXED, CREDS, SERVER])
+ self.check_run(command)
+ expected = open(EXPECTED_OUTPUT % i).read()
+ actual = open(output).read()
+ self.assertStringsEqual(expected, actual)
+
+ def test_summary_replay_no_fixed(self):
+ """Ensure a summary file with no fixed password fails
+ """
+ command = [SCRIPT, MODEL, CREDS, SERVER]
+ self.check_exit_code(command, 1)
def test_model_replay(self):
"""Ensure a model can be replayed against a DC
"""
-
- model = "testdata/traffic-sample-very-short.model"
- command = "%s %s-D 5 %s %s" % (SCRIPT, model, FIXED, STD_OPTIONS)
+ command = [SCRIPT, MODEL,
+ FIXED,
+ '-D2', '-S0.1',
+ CREDS, SERVER]
self.check_run(command)
def test_generate_users_only_no_password(self):
@@ -74,5 +107,7 @@ class TrafficLearnerTests(BlackboxTestCase):
"""
options = ("--generate-users-only --number-of-users 20 "
"--number-of-groups 5 --average-groups-per-user 2")
- command = "%s %s %s" % (SCRIPT, options, STD_OPTIONS)
+ command = "%s %s %s %s" % (SCRIPT, options, CREDS, SERVER)
+ self.check_exit_code(command, 1)
+ command = "%s %s %s %s %s" % (SCRIPT, MODEL, options, CREDS, SERVER)
self.check_exit_code(command, 1)