build.tracing.trace_pkt._create_ip_packet()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 7
nop 1
dl 0
loc 14
ccs 7
cts 7
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
"""
2
    This module has functions used to pack and unpack the Ethernet frame
3
     used by PacketOuts and PacketIns.
4
"""
5
6
7 1
import dill
8 1
from pyof.foundation.network_types import Ethernet, IPv4, VLAN
9 1
from napps.amlight.sdntrace import constants
10 1
from napps.amlight.sdntrace.tracing.trace_msg import TraceMsg
11 1
from napps.amlight.sdntrace.shared.extd_nw_types import TCP, UDP
12 1
from napps.amlight.sdntrace.shared.switches import Switches
13 1
from napps.amlight.sdntrace.shared.colors import Colors
14
15
16 1
def generate_trace_pkt(trace_entries, color, r_id):
17
    """ Receives the REST/PUT to generate a PacketOut
18
    data needs to be serialized. The goal is always to create
19
    a packet with data being the TraceMsg to differentiate different
20
    traces running in parallel. We will stack layers depending of
21
    the user request. If user submits just a VLAN ID, we will use
22
    ethertype 88b5 and add TraceMsg after it. Same for IP, however
23
    the protocol will be 65535. If user provides all the way to TCP/UDP
24
    we will add TraceMsg after it. First thing is to discover
25
    what it is that the user has provided.
26
27
    Args:
28
        trace_entries: TraceEntries provided by user or collected from PacketIn
29
        color: result from Coloring Napp for a specific DPID
30
        r_id: request ID
31
32
    Returns:
33
        in_port: in_port
34
        pkt: serialized Ethernet frame
35
    """
36
37 1
    ethernet = _create_ethernet_frame(trace_entries, color)
38
39 1
    msg = TraceMsg(r_id)
40
41 1
    if ethernet.ether_type == constants.IPV4:
42 1
        ip_pkt = _create_ip_packet(trace_entries)
43 1
        if ip_pkt.protocol == constants.TCP:
44 1
            tp_pkt = _create_tcp_packet(trace_entries)
45 1
            tp_pkt.data = dill.dumps(msg)
46 1
            ip_pkt.data = tp_pkt.pack(ip_pkt)
47 1
        elif ip_pkt.protocol == constants.UDP:
48 1
            udp_pkt = _create_udp_packet(trace_entries)
49 1
            udp_pkt.data = dill.dumps(msg)
50 1
            ip_pkt.data = udp_pkt.pack(ip_pkt)
51
        else:
52 1
            ip_pkt.data = dill.dumps(msg)
53
54 1
        ethernet.data = ip_pkt.pack()
55
    else:
56
        ethernet.data = dill.dumps(msg)
57
58 1
    pkt = ethernet.pack()
59 1
    return trace_entries.in_port, pkt
60
61
62 1
def prepare_next_packet(trace_entries, result, event):
63
    """ Used to support VLAN translation. Currently, it does not
64
    support translation of other fields, such as MAC addresses.
65
66
    Args:
67
        trace_entries: TraceEntries provided by user or collected from PacketIn
68
        result: Result of the last Trace Probe sent.
69
        event: PacketIn event
70
71
    Returns:
72
        trace_entries: TraceEntries customized with new VLAN
73
        color: result from Coloring Napp for a specific DPID
74
        switch: DPID
75
    """
76 1
    dpid = result['dpid']
77 1
    switch, color = _get_node_color_from_dpid(dpid)
78
79 1
    trace_entries.dpid = dpid
80
81 1
    if event.content['message'].header.version == 1:
82 1
        in_port = event.content['message'].in_port.value
83 1
        trace_entries.in_port = in_port
84
    else:
85
        in_port = event.message.in_port
86
        trace_entries.in_port = in_port
87
88 1
    vlan = _get_vlan_from_pkt(event.content['message'].data.value)
89 1
    if vlan:
90 1
        trace_entries.dl_vlan = vlan
91 1
    return trace_entries, color, switch
92
93
94 1
def process_packet(ethernet):
95
    """Navigates through the Ethernet payload looking for the
96
    TraceMsg(). TraceMsg is the payload after all protocols of
97
    the TCP/IP stack.
98
99
    Args:
100
        ethernet: ethernet frame
101
102
    Returns:
103
        TraceMsg in the binary format
104
    """
105 1
    offset = 0
106
107 1
    trace_msg = ethernet.data.value
108
109 1
    if ethernet.ether_type == constants.IPV4:
110 1
        ip_pkt = IPv4()
111 1
        ip_pkt.unpack(ethernet.data.value, offset)
112 1
        offset += ip_pkt.length
113 1
        trace_msg = ip_pkt.data
114
115 1
        if ip_pkt.protocol == constants.TCP:
116 1
            transport = TCP()
117 1
            transport.unpack(ip_pkt.data)
118 1
            trace_msg = transport.data
119
120 1
        elif ip_pkt.protocol == constants.UDP:
121 1
            transport = UDP()
122 1
            transport.unpack(ip_pkt.data)
123 1
            trace_msg = transport.data
124
125 1
    return trace_msg
126
127
128 1
def _create_ethernet_frame(trace_entries, color):
129
    """ Create an Ethernet frame using TraceEntries
130
    and color (dl_src)
131
132
    Args:
133
        trace_entries: TraceEntries provided by user or collected from PacketIn
134
        color: field and value that indicate the color
135
    Returns:
136
        ethernet frame
137
    """
138 1
    ethernet = Ethernet()
139 1
    ethernet.ether_type = trace_entries.dl_type
140
141 1
    ethernet.source = color['color_value']
142 1
    ethernet.destination = trace_entries.dl_dst
143
144 1
    if trace_entries.dl_vlan:
145 1
        vlan = VLAN(vid=trace_entries.dl_vlan,
146
                    pcp=trace_entries.dl_vlan_pcp)
147 1
        ethernet.vlans.append(vlan)
148 1
    return ethernet
149
150
151 1
def _create_ip_packet(trace_entries) -> IPv4:
152
    """ Create an IP packet using TraceEntries
153
154
    Args:
155
        trace_entries: TraceEntries provided by user or collected from PacketIn
156
    Returns:
157
        ip packet
158
    """
159 1
    ip_pkt = IPv4()
160 1
    ip_pkt.destination = trace_entries.nw_dst
161 1
    ip_pkt.source = trace_entries.nw_src
162 1
    ip_pkt.dscp = trace_entries.nw_tos
163 1
    ip_pkt.protocol = trace_entries.nw_proto
164 1
    return ip_pkt
165
166
167 1
def _create_tcp_packet(trace_entries) -> TCP:
168
    """ Create a TCP packet using TraceEntries (FUTURE)
169
170
    Args:
171
        trace_entries: TraceEntries provided by user or collected from PacketIn
172
    Returns:
173
        tcp packet
174
    """
175 1
    tcp_pkt = TCP()
176 1
    tcp_pkt.src_port = trace_entries.tp_src
177 1
    tcp_pkt.dst_port = trace_entries.tp_dst
178 1
    return tcp_pkt
179
180
181 1
def _create_udp_packet(trace_entries) -> UDP:
182
    """ Create an UDP datagram using TraceEntries (FUTURE)
183
184
    Args:
185
        trace_entries: TraceEntries provided by user or collected from PacketIn
186
    Returns:
187
        tcp message
188
    """
189 1
    udp_pkt = UDP()
190 1
    udp_pkt.src_port = trace_entries.tp_src
191 1
    udp_pkt.dst_port = trace_entries.tp_dst
192 1
    return udp_pkt
193
194
195 1
def _get_node_color_from_dpid(dpid):
196
    """ Get node color from Coloring Napp
197
198
    Args:
199
        dpid: switch DPID
200
    Returns:
201
        switch and color
202
        0 for not Found
203
    """
204 1
    for switch in Switches().get_switches():
205 1
        if dpid == switch.dpid:
206 1
            return switch, Colors().get_switch_color(switch.dpid)
207 1
    return 0, 0
208
209
210 1
def _get_vlan_from_pkt(data):
211
    """ Get VLAN ID from frame. Used for VLAN Translation
212
213
    Args:
214
        data: Ethernet Frame
215
    Returns:
216
        VLAN VID
217
    """
218 1
    ethernet = Ethernet()
219 1
    ethernet.unpack(data)
220 1
    vlans = ethernet.vlans
221 1
    if vlans:
222 1
        return vlans[0].vid
223
    return None
224