This documentation explains in details how SDN-WISE works. We suggest to get started by downloading our code from GitHub:
git clone https://github.com/sdnwiselab/sdn-wise-java.git
SDN-WISE is written in Java, but we also provide a C porting for Contiki. For this reason depending on the context we will discuss the relevant Java/C code.
First of all let’s start with the sdn-wise-java Maven project. You can read more on Maven here https://maven.apache.org/
This project is divided into three modules:
In this document we will focus on the Core module and in particular on SDN-WISE packets. Architectural details can be found in the papers section of the website so we will take for granted that you are already familiar with the concepts of Control and Data plane, WISE Flow Table, and the messages that SDN-WISE nodes exchange.
The Core module is divided into four packages:
Packet contains the classes that model the messages exchanged by SDN-WISE nodes, Flowtable contains the classes related to the WISE Flow Table, Function is used to reprogram “Over The Air” a node and Util contains all the stuff that did not fit in the previous packages, basically a class that represent the address of a node, the log formatter used in the project, a class that models the concept of neighbor and a utility class that contains byte manipulation functions.
The most important class in this package is NetworkPacket. It is extended by all the classes in the package and model the header of the SDN-WISE packets. It contains the common constructors used to instantiate packets, and the relative methods to interact with the header’s fields.
All the SDN-WISE Packets have the following header fields:
Byte(s) | Name | Description |
---|---|---|
0 |
NET |
Identifier of the network |
1 |
LEN |
Total length of the packet |
2-3 |
DST |
Destination address |
4-5 |
SRC |
Source address |
6 |
TYP |
Packet type |
7 |
TTL |
No. of hops remaining |
8-9 |
NXH |
Next hop address |
A detailed description of the fields is provided in the original paper on SDN-WISE. For the NetworkPacket class, as well as all the following classes, there is always a getter and a setter for the entries reported in the Packet Layout table. These methods are usually called getName/setName where Name is the value reported in the Name column written in CamelCase. E.g. getNet and setNet, getLen and setLen, etc.
For this kind of packets the field TYP is set to 0. Except the header, this packet is just payload.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10-… |
Payload |
Data content |
To create a Data packet use the DataPacket class. Its main constructor is:
public DataPacket(int net, NodeAddress src, NodeAddress dst, byte[] payload)
As specified before there is a setter and a getter for the payload and they are called respectively getPayload and setPayload
TYP = 1. The Destination is always broadcast. In this case NXH contains the address of the sink for the source node. This packet reports the distance from the sink of the source node and its battery level.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10 |
Distance |
Distance from the sink in no. of hops |
11 |
Battery |
Battery level. Full = 0xFF, Empty = 0x00 |
To create a Beacon packet use the BeaconPacket class. Its main constructor is:
public BeaconPacket(int net, NodeAddress src, NodeAddress sink, int distance, int battery)
there is a getter and a setter for both Distance and Battery, and a getter and a setter for the SinkAddress of the node.
public BeaconPacket setSinkAddress(NodeAddress addr)
public NodeAddress getSinkAddress()
TYP = 2. Contains the list of the nodes at 1 hop distance from the source node. There is a maximum of 35 neighbors for each Report packet. This packet also reports informations on the distance from the sink of the source node and its battery level. By default this packet is always routed towards the sink of the receiving node. After each node in the list of neighbors there is a link quality indicator for the link between the source node and the node in the list.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10 |
Distance |
Distance from the sink in no. of hops |
11 |
Battery |
Battery level. Full = 0xFF, Empty = 0x00 |
12 |
NeigborsSize |
The no. of nodes in the neighbors’ list |
13-14 |
NeighborAddress 1 |
Address of the 1st neighbor in the list |
15 |
LinkQuality 1 |
Rssi between the 1st neighbor and the source |
…-… |
NeighborAddress n |
Address of the n-th neighbor in the list |
… |
LinkQuality n |
Rssi between the n-th neighbor and the source |
To create a Report packet use the ReportPacket class.
public ReportPacket(int net, NodeAddress src, NodeAddress dst, int distance, int battery)
This class extends BeaconPacket and adds a getter and a setter for the number of nodes in the neighbors’ list plus different methods to deal with this list.
public int getNeigborsSize()
public ReportPacket setNeigborsSize(int value)
public NodeAddress getNeighborAddress(int i)
public ReportPacket setNeighborAddressAt(NodeAddress addr, int i)
public int getLinkQuality(int i)
public ReportPacket setLinkQualityAt(byte value, int i)
public HashMap<NodeAddress, Byte> getNeighbors()
public ReportPacket setNeighbors(HashMap<NodeAddress, Byte> map)
TYP = 3. This packet encapsulates a packet that has no match in a Flow Table. By default a Request packet is always routed toward the sink of the receiving node. If the unmatched packet fits in a single Request packet then Part is set to 0 and Total = 1. Otherwise, it is broken into two pieces and encapsulated in two different Request packets. In this case the first part will have Part = 0 and Total = 2, while the second part will have Part = 1 and Total = 2. Each request has an ID. An ID is repeated after 255 requests. The unmatched packet starts at byte 13.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10 |
Id |
Identifier of the request |
11 |
Part |
Which part of the Request packet has been sent |
12 |
Total |
The total no. of parts of the Request packet |
13-… |
Unmatched Packet |
The unmatched packet |
To create a Request packet use the following static method of the RequestPacket class:
public static RequestPacket[] createPackets(int net, NodeAddress src, NodeAddress dest, byte id, byte[] buf)
This method returns an array of RequestPackets depending on the size of the unmatched packet. To merge two Request Packet and get the unmatched packet use:
public static NetworkPacket mergePackets(RequestPacket rp0, RequestPacket rp1)
TYP = 4. A Response packet contains a Flow Table entry sent from the Control Plane. For further details on the format of an entry and how to create it, please check the FlowTable section of this document. In future version of SDN-WISE this packet may be replaced by a Config packet.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10-… |
Rule |
The rule sent from the Control Plane |
To create a Request packet use the following constructor of the ResponsePacket class:
public ResponsePacket(int net, NodeAddress src, NodeAddress dst, FlowTableEntry entry)
TYP = 5. The OpenPath packet is used to reduce the number of control messages sent from the control plane. In particular it creates a path in the network. The content of the packet is basically a set of windows and a list of addresses. The list of addresses creates the path in the network. After receiving this kind of packet, each node in the path will be able to reach the first and the last node in the path, by sending its packets to the previous (for the first) or the next node (for the last) in the list. As an example a node at position n will learn two rules:
It also possible to add some more conditions to the previous rules by adding windows in the packet. For example it is possible to specify a condition on the payload
To achieve this result we add a window in the OpenPath packet. More details on how to create a window can be found in the Windows section of this document. Finally, when a node has learned its rules, it sends the packet to the following node in the path. This process is repeated until the packet reaches the end of the path.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10 |
WindowsSize |
The no. of windows in the OpenPath packet |
11-15 |
Window 1 |
The 1st Window added to all the rules |
…-… |
Window n |
The n-th Window added to all the rules |
…-… |
Address 1 |
The 1st Node in the path |
…-… |
Address k |
The k-th Node in the path |
An OpenPath packet can be created using the following constructor:
public OpenPathPacket(int net, NodeAddress src, NodeAddress dst, List<NodeAddress> path)
Methods are provided to set and get the path and to set and get the list of windows:
public OpenPathPacket setPath(List<NodeAddress> path)
public List<NodeAddress> getPath()
public OpenPathPacket setWindows(List<Window> conditions)
public final List<Window> getWindows()
TYP = 6. The Config packet is used to read/write configuration parameters. These parameters are:
ID | Name | Description |
---|---|---|
0 |
RESET |
Hardware reset |
1 |
MY_NET |
Node Network ID |
2 |
MY_ADDRESS |
The SDN-WISE address of the node |
3 |
PACKET_TTL |
The default TTL for a new packet |
4 |
RSSI_MIN |
The minimum RSSI value to consider a link reliable |
5 |
BEACON_PERIOD |
A Beacon packet is sent every BEACON_MAX seconds |
6 |
REPORT_PERIOD |
A Report packet is sent every REPORT_MAX seconds |
7 |
RESET_PERIOD |
NXTHOP vs Sink is deleted after RESET_PERIOD reports |
8 |
RULE_TTL |
A flow table entry is deleted after ENTRY_TTL seconds |
9 |
ADD_ALIAS |
Add a node address alias |
10 |
REM_ALIAS |
Remove a node address alias |
11 |
GET_ALIAS |
Get the node address alias at a certain position |
12 |
ADD_RULE |
Add a flow table entry |
13 |
REM_RULE |
Remove a flow table entry at a certain position |
14 |
GET_RULE |
Get the flow table entry at a certain position |
15 |
ADD_FUNCTION |
Add a function |
16 |
REM_FUNCTION |
Remove the function at a certain position |
17 |
GET_FUNCTION |
Get the function ID at a certain position |
The Config packet contains as payload the ID of the parameters to read/write, a bit indicating if the packet is a “read” or a “write” and a field of variable size containing the value to write or the value read.
READ The Control plane creates a Config Packet, with the read/write bit set to 0, and specifies the ID of the parameter. The node will send back the response with the reading appended in the packet.
WRITE The Control plane creates a Config Packet, with the read/write bit set to 1, and specifies the ID of the parameter and the new value. The node receives the packet and updates its values accordingly.
GET/ADD/REMOVE If the Control plane wants to GET or REMOVE an entry/alias/function it has to specify the index of the item to get/remove or the item itself if it wants to add it.
Anyway, from a user points of view, the AbstractController class contains all the methods needed to read/write/get/add/remove thus no direct interaction with the packets is required. More details will be provided in the Control Plane documentation.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10 |
ConfigId |
R/W bit + ID |
11-… |
Params(Optional) |
The value to be set or read |
To create a Config packet to read a value use the constructor:
public ConfigPacket(int netId, NodeAddress src, NodeAddress dst, ConfigProperty read)
To create a Config packet to write a value use:
public ConfigPacket(int net, NodeAddress src, NodeAddress dst, ConfigProperty write, byte[] value)
For more information and some examples on how to use the Config packets check the AbstractController and ControllerInterface classes inside the com.github.sdnwiselab.sdnwise.controller package.
TYP = 7. The RegProxy packet is used to notify the existence of a Sink to the Control Plane and to associate some information with it. Some controllers may register the Sink node as a switch so we provide a Dpid, a MAC address, a physical port, and an InetSocketAddress.
Byte(s) | Name | Description |
---|---|---|
0-9 |
Header |
SDN-WISE Packet header |
10-17 |
DPID |
DPID of the Sink |
18-23 |
MAC |
MAC address of the sink |
24-31 |
Port |
Physical port to which the sink is connected |
31-34 |
IP |
IP address of the sink |
34-35 |
TCP |
TCP port of the sink |
To create a RegProxy packet use the following constructor:
public RegProxyPacket(int net, NodeAddress src, String dPid, String mac, long port, InetSocketAddress isa)
The only exception to the usual list of setters and getters is for the IP address and TCP port because an InetSocketAddress object is used:
public RegProxyPacket setInetSocketAddress(InetSocketAddress isa)
public InetSocketAddress getInetSocketAddress()
Work in progress…
The FlowTable of each node consists in a collection of FlowTableEntry objects. Each FlowTableEntry is made of a list of Windows, a list of Actions, and some Statistical information.
Each com.github.sdnwiselab.sdnwise.flowtable.Window allows to set a condition to be verified in order to execute the actions. A condition is made of three parts a lefthandside, a righthandside, and an operator
For both handsides it is possible to specify the location of the operand (using the method setLhsLocation and setRhsLocation) and the address (using the method setLhs or setRhs).
The loacation of a handsides can be PACKET, STATUS, or CONST (These values are in the com.github.sdnwiselab.sdnwise.flowtable.FlowTableInterface interface) while a the operator can be choosen among a list of possible operators:
EQUAL,
GREATER,
GREATER_OR_EQUAL,
LESS,
LESS_OR_EQUAL,
NOT_EQUAL
For example: to create a window that checks that the type (i.e. the byte at position 6) of a packet is equal to 10 you can write:
new Window()
.setLhsLocation(PACKET)
.setLhs(6)
.setOperator(EQUAL)
.setRhsLocation(CONST)
.setRhs(10)
The actions are the events that are executed when all the conditions are verified. There are different types of actions:
NULL: No Action
ASK: Send the packet to the controller, asking for a new FlowTableEntry. It does not requires any parameter and can be created using:
new AskAction()
DROP: Discard a packet. It does not requires any parameter and can be created using:
new DropAction()
FORWARD_B: Forward in broadcast to all the device in range. It does not requires any parameter and can be created using:
new ForwardBroadcastAction()
FORWARD_U: Forward in unicast to an address. It requires as input the NodeAddress of the device to which the packet is going to be forwarded. As an example, if we want to forward to node 3 then:
new ForwardUnicastAction(new NodeAddress(3))
FUNCTION: Execute a function installed on the device. It requires the id of the function, that is going to be called and a list of parameters. As an example, if we want to call the function n 5 passing as arguments 10 integers so can use:
new FunctionAction(new byte[]{5, 1, 9, 8, 7, 6, 5, 4, 3, 2, 1,}));
MATCH: Match the packet against the FlowTable of the node. It does not requires any parameter and can be created using:
new MatchAction()
SET: Set a value in the status of the node or in the packet. The way a set is executed is similar to the matching in the window, with the difference that the list of operators is the following:
ADD = sum
AND = binary AND
DIV = division
MOD = modulo operation
MUL = multiplication
OR = binary OR
SUB = subtraction
XOR = binary XOR
It is also possible to specify where the result of the set operation is placed by using the setResLocation function. The possible locations are
PACKET
STATUS
As an example to set the 13th byte of a packet equal to the sum of the content of byte 12 and byte 13 SET P.11 = P.12 + P.13:
new SetAction()
.setLhsLocation(PACKET)
.setLhs(12)
.setOperator(ADD)
.setRhsLocation(PACKET)
.setRhs(13)
.setResLocation(PACKET)
.setRes(11));