A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Documentation ▼
Installation
Manual
Models
Contributing
Wiki
Development ▼
API Docs
Issue Tracker
Merge Requests
API
Loading...
Searching...
No Matches
openflow-switch-test-suite.cc
Go to the documentation of this file.
1
/*
2
* Copyright (c) 2011 Blake Hurd
3
*
4
* SPDX-License-Identifier: GPL-2.0-only
5
*
6
* Author: Blake Hurd <naimorai@gmail.com>
7
*/
8
9
// An essential include is test.h
10
#include "ns3/openflow-interface.h"
11
#include "ns3/openflow-switch-net-device.h"
12
#include "ns3/test.h"
13
14
// Do not put your test classes in namespace ns3. You may find it useful
15
// to use the using directive to access the ns3 namespace directly
16
using namespace
ns3
;
17
18
/**
19
* @ingroup openflow-tests
20
*
21
* @brief OpenFlow Test
22
*/
23
class
SwitchFlowTableTestCase
:
public
TestCase
24
{
25
public
:
26
SwitchFlowTableTestCase
()
27
:
TestCase
(
"Switch test case"
)
28
{
29
m_chain
=
chain_create
();
30
}
31
32
~SwitchFlowTableTestCase
()
override
33
{
34
chain_destroy
(
m_chain
);
35
}
36
37
private
:
38
void
DoRun
()
override
;
39
40
sw_chain
*
m_chain
;
//!< OpenFlow service function chain
41
};
42
43
void
44
SwitchFlowTableTestCase::DoRun
()
45
{
46
// Flow Table implementation is used by the OpenFlowSwitchNetDevice under the chain_ methods
47
// we should test its implementation to verify the flow table works.
48
49
// Initialization
50
time_init
();
// OFSI requires this, otherwise we crash before we can do anything.
51
52
size_t
actions_len
= 0;
// Flow is created with 0 actions.
53
int
output_port
= 0;
// Flow will be modified later with an action to output on port 0.
54
55
Mac48Address
dl_src
(
"00:00:00:00:00:00"
);
56
Mac48Address
dl_dst
(
"00:00:00:00:00:01"
);
57
Ipv4Address
nw_src
(
"192.168.1.1"
);
58
Ipv4Address
nw_dst
(
"192.168.1.2"
);
59
int
tp_src
= 5000;
60
int
tp_dst
= 80;
61
62
// Create an sw_flow_key; in actual usage this is generated from the received packet's headers.
63
sw_flow_key
key;
64
key.wildcards = 0;
65
66
key.flow.in_port =
htons
(0);
67
68
key.flow.dl_vlan =
htons
(
OFP_VLAN_NONE
);
69
key.flow.dl_type =
htons
(
ETH_TYPE_IP
);
70
key.flow.nw_proto =
htons
(
IP_TYPE_UDP
);
71
72
key.flow.reserved = 0;
73
key.flow.mpls_label1 =
htonl
(
MPLS_INVALID_LABEL
);
74
key.flow.mpls_label2 =
htonl
(
MPLS_INVALID_LABEL
);
75
76
// Set Mac Addresses
77
dl_src
.CopyTo(key.flow.dl_src);
78
dl_dst
.CopyTo(key.flow.dl_dst);
79
80
// Set IP Addresses
81
key.flow.nw_src =
htonl
(
nw_src
.Get());
82
key.flow.nw_dst =
htonl
(
nw_dst
.Get());
83
84
// Set TCP/UDP Ports
85
key.flow.tp_src =
htonl
(
tp_src
);
86
key.flow.tp_dst =
htonl
(
tp_dst
);
87
88
// Create flow
89
ofp_flow_mod
ofm
;
90
ofm
.header.version =
OFP_VERSION
;
91
ofm
.header.type =
OFPT_FLOW_MOD
;
92
ofm
.header.length =
htons
(
sizeof
(
ofp_flow_mod
) +
actions_len
);
93
ofm
.command =
htons
(
OFPFC_ADD
);
94
ofm
.idle_timeout =
htons
(
OFP_FLOW_PERMANENT
);
95
ofm
.hard_timeout =
htons
(
OFP_FLOW_PERMANENT
);
96
ofm
.buffer_id =
htonl
(-1);
97
ofm
.priority =
OFP_DEFAULT_PRIORITY
;
98
99
ofm
.match.wildcards = key.wildcards;
// Wildcard fields
100
ofm
.match.in_port = key.flow.in_port;
// Input switch port
101
memcpy
(
ofm
.match.dl_src, key.flow.dl_src,
sizeof
ofm
.match.dl_src);
// Ethernet source address.
102
memcpy
(
ofm
.match.dl_dst,
103
key.flow.dl_dst,
104
sizeof
ofm
.match.dl_dst);
// Ethernet destination address.
105
ofm
.match.dl_vlan = key.flow.dl_vlan;
// Input VLAN OFP_VLAN_NONE;
106
ofm
.match.dl_type = key.flow.dl_type;
// Ethernet frame type ETH_TYPE_IP;
107
ofm
.match.nw_proto = key.flow.nw_proto;
// IP Protocol
108
ofm
.match.nw_src = key.flow.nw_src;
// IP source address
109
ofm
.match.nw_dst = key.flow.nw_dst;
// IP destination address
110
ofm
.match.tp_src = key.flow.tp_src;
// TCP/UDP source port
111
ofm
.match.tp_dst = key.flow.tp_dst;
// TCP/UDP destination port
112
ofm
.match.mpls_label1 = key.flow.mpls_label1;
// Top of label stack
113
ofm
.match.mpls_label2 = key.flow.mpls_label1;
// Second label (if available)
114
115
// Build a sw_flow from the ofp_flow_mod
116
sw_flow
*
flow
=
flow_alloc
(
actions_len
);
117
NS_TEST_ASSERT_MSG_NE
(
flow
, 0,
"Cannot allocate memory for the flow."
);
118
119
flow_extract_match
(&
flow
->key, &
ofm
.match);
120
121
// Fill out flow.
122
flow
->priority =
flow
->key.wildcards ?
ntohs
(
ofm
.priority) : -1;
123
flow
->idle_timeout =
ntohs
(
ofm
.idle_timeout);
124
flow
->hard_timeout =
ntohs
(
ofm
.hard_timeout);
125
flow
->used =
flow
->created =
time_now
();
126
flow
->sf_acts->actions_len =
actions_len
;
127
flow
->byte_count = 0;
128
flow
->packet_count = 0;
129
memcpy
(
flow
->sf_acts->actions,
ofm
.actions,
actions_len
);
130
131
// Insert the flow into the Flow Table
132
NS_TEST_ASSERT_MSG_EQ
(
chain_insert
(
m_chain
,
flow
), 0,
"Flow table failed to insert Flow."
);
133
134
// Use key to match the flow to verify we created it correctly.
135
NS_TEST_ASSERT_MSG_NE
(
chain_lookup
(
m_chain
, &key),
136
0,
137
"Key provided doesn't match to the flow that was created from it."
);
138
139
// Modify key to make sure the flow doesn't match it.
140
dl_dst
.CopyTo(key.flow.dl_src);
141
dl_src
.CopyTo(key.flow.dl_dst);
142
key.flow.nw_src =
htonl
(
nw_dst
.Get());
143
key.flow.nw_dst =
htonl
(
nw_src
.Get());
144
key.flow.tp_src =
htonl
(
tp_dst
);
145
key.flow.tp_dst =
htonl
(
tp_src
);
146
147
NS_TEST_ASSERT_MSG_EQ
(
chain_lookup
(
m_chain
, &key),
148
0,
149
"Key provided shouldn't match the flow but it does."
);
150
151
// Modify key back to matching the flow so we can test flow modification.
152
dl_dst
.CopyTo(key.flow.dl_dst);
153
dl_src
.CopyTo(key.flow.dl_src);
154
key.flow.nw_src =
htonl
(
nw_src
.Get());
155
key.flow.nw_dst =
htonl
(
nw_dst
.Get());
156
key.flow.tp_src =
htonl
(
tp_src
);
157
key.flow.tp_dst =
htonl
(
tp_dst
);
158
159
// Testing Flow Modification; chain_modify should return 1, for 1 flow modified.
160
// Create output-to-port action
161
ofp_action_output
acts
[1];
162
acts
[0].type =
htons
(
OFPAT_OUTPUT
);
163
acts
[0].len =
htons
(
sizeof
(
ofp_action_output
));
164
acts
[0].port =
output_port
;
165
166
uint16_t priority = key.wildcards ?
ntohs
(
ofm
.priority) : -1;
167
NS_TEST_ASSERT_MSG_EQ
(
168
chain_modify
(
m_chain
, &key, priority,
false
, (
const
ofp_action_header
*)
acts
,
sizeof
(
acts
)),
169
1,
170
"Flow table failed to modify Flow."
);
171
172
// Testing Flow Deletion; chain_delete should return 1, for 1 flow deleted.
173
// Note: By providing chain_delete with output_port, the flow must have an action that outputs
174
// on that port in order to delete the flow. This is how we verify that our action was truly
175
// added via the flow modification.
176
NS_TEST_ASSERT_MSG_EQ
(
chain_delete
(
m_chain
, &key,
output_port
, 0, 0),
177
1,
178
"Flow table failed to delete Flow."
);
179
NS_TEST_ASSERT_MSG_EQ
(
chain_lookup
(
m_chain
, &key),
180
0,
181
"Key provided shouldn't match the flow but it does."
);
182
}
183
184
/**
185
* @ingroup openflow-tests
186
*
187
* @brief OpenFlow TestSuite
188
*/
189
class
SwitchTestSuite
:
public
TestSuite
190
{
191
public
:
192
SwitchTestSuite
();
193
};
194
195
SwitchTestSuite::SwitchTestSuite
()
196
:
TestSuite
(
"openflow"
,
Type
::UNIT)
197
{
198
AddTestCase
(
new
SwitchFlowTableTestCase
, TestCase::Duration::QUICK);
199
}
200
201
/// Do not forget to allocate an instance of this TestSuite
202
static
SwitchTestSuite
switchTestSuite
;
SwitchFlowTableTestCase
OpenFlow Test.
Definition
openflow-switch-test-suite.cc:24
SwitchFlowTableTestCase::SwitchFlowTableTestCase
SwitchFlowTableTestCase()
Definition
openflow-switch-test-suite.cc:26
SwitchFlowTableTestCase::~SwitchFlowTableTestCase
~SwitchFlowTableTestCase() override
Definition
openflow-switch-test-suite.cc:32
SwitchFlowTableTestCase::m_chain
sw_chain * m_chain
OpenFlow service function chain.
Definition
openflow-switch-test-suite.cc:40
SwitchFlowTableTestCase::DoRun
void DoRun() override
Implementation to actually run this TestCase.
Definition
openflow-switch-test-suite.cc:44
SwitchTestSuite
OpenFlow TestSuite.
Definition
openflow-switch-test-suite.cc:190
SwitchTestSuite::SwitchTestSuite
SwitchTestSuite()
Definition
openflow-switch-test-suite.cc:195
ns3::Ipv4Address
Ipv4 addresses are stored in host order in this class.
Definition
ipv4-address.h:31
ns3::Mac48Address
an EUI-48 address
Definition
mac48-address.h:35
ns3::TestCase
encapsulates test code
Definition
test.h:1050
ns3::TestCase::AddTestCase
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition
test.cc:292
ns3::TestSuite
A suite of tests to run.
Definition
test.h:1267
ns3::TestSuite::Type
Type
Type of test.
Definition
test.h:1274
ns3::Create
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition
ptr.h:436
NS_TEST_ASSERT_MSG_EQ
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition
test.h:134
NS_TEST_ASSERT_MSG_NE
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition
test.h:554
ns3
Every class exported by the ns3 library is enclosed in the ns3 namespace.
switchTestSuite
static SwitchTestSuite switchTestSuite
Do not forget to allocate an instance of this TestSuite.
Definition
openflow-switch-test-suite.cc:202
src
openflow
test
openflow-switch-test-suite.cc
Generated on Mon Dec 15 2025 15:22:02 for ns-3 by
1.9.8