Passed
Push — master ( d84e35...e2f2a2 )
by Humberto
01:40 queued 11s
created

build.v0x04.utils.send_echo()   A

Complexity

Conditions 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 3
nop 2
dl 0
loc 7
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
"""Utilities module for of_core OpenFlow v0x04 operations."""
2 1
from pyof.v0x04.common.action import ControllerMaxLen
3 1
from pyof.v0x04.common.port import PortConfig
4 1
from pyof.v0x04.controller2switch.common import ConfigFlag, MultipartType
5 1
from pyof.v0x04.controller2switch.multipart_request import (FlowStatsRequest,
6
                                                            MultipartRequest,
7
                                                            PortStatsRequest)
8 1
from pyof.v0x04.controller2switch.set_config import SetConfig
9 1
from pyof.v0x04.symmetric.echo_request import EchoRequest
10 1
from pyof.v0x04.symmetric.hello import Hello
11
12 1
from kytos.core.events import KytosEvent
13 1
from kytos.core.interface import Interface
14 1
from napps.kytos.of_core.utils import emit_message_out
15
16
17 1
def update_flow_list(controller, switch):
18
    """Request flow stats from switches.
19
20
    Args:
21
        controller(:class:`~kytos.core.controller.Controller`):
22
            the controller being used.
23
        switch(:class:`~kytos.core.switch.Switch`):
24
            target to send a stats request.
25
26
    Returns:
27
        int: multipart request xid
28
29
    """
30 1
    multipart_request = MultipartRequest()
31 1
    multipart_request.multipart_type = MultipartType.OFPMP_FLOW
32 1
    multipart_request.body = FlowStatsRequest()
33 1
    emit_message_out(controller, switch.connection, multipart_request)
34 1
    return multipart_request.header.xid
35
36
37 1
def request_port_stats(controller, switch):
38
    """Request port stats from switches.
39
40
    Args:
41
        controller(:class:`~kytos.core.controller.Controller`):
42
            the controller being used.
43
        switch(:class:`~kytos.core.switch.Switch`):
44
            target to send a stats request.
45
46
    Returns:
47
        int: multipart request xid
48
49
    """
50 1
    multipart_request = MultipartRequest()
51 1
    multipart_request.multipart_type = MultipartType.OFPMP_PORT_STATS
52 1
    multipart_request.body = PortStatsRequest()
53 1
    emit_message_out(controller, switch.connection, multipart_request)
54 1
    return multipart_request.header.xid
55
56
57 1
def send_desc_request(controller, switch):
58
    """Request vendor-specific switch description.
59
60
    Args:
61
        controller(:class:`~kytos.core.controller.Controller`):
62
            the controller being used.
63
        switch(:class:`~kytos.core.switch.Switch`):
64
            target to send a stats request.
65
    """
66 1
    multipart_request = MultipartRequest()
67 1
    multipart_request.multipart_type = MultipartType.OFPMP_DESC
68 1
    emit_message_out(controller, switch.connection, multipart_request)
69
70
71 1
def send_port_request(controller, connection):
72
    """Send a Port Description Request after the Features Reply."""
73 1
    port_request = MultipartRequest()
74 1
    port_request.multipart_type = MultipartType.OFPMP_PORT_DESC
75 1
    emit_message_out(controller, connection, port_request)
76
77
78 1
def handle_features_reply(controller, event):
79
    """Handle OF v0x04 features_reply message events.
80
81
    This is the end of the Handshake workflow of the OpenFlow Protocol.
82
83
    Parameters:
84
        controller (Controller): Controller being used.
85
        event (KytosEvent): Event with features reply message.
86
87
    """
88 1
    connection = event.source
89 1
    features_reply = event.content['message']
90 1
    dpid = features_reply.datapath_id.value
91
92 1
    switch = controller.get_switch_or_create(dpid=dpid,
93
                                             connection=connection)
94 1
    send_port_request(controller, connection)
95
96 1
    switch.update_features(features_reply)
97
98 1
    return switch
99
100
101 1
def handle_port_desc(controller, switch, port_list):
102
    """Update interfaces on switch based on port_list information."""
103 1
    for port in port_list:
104 1
        interface = switch.get_interface_by_port_no(port.port_no.value)
105 1
        config = port.config
106 1
        if (port.supported == 0 and
107
                port.curr_speed.value == 0 and
108
                port.max_speed.value == 0):
109
            config = PortConfig.OFPPC_NO_FWD
110
111 1
        if interface:
112 1
            interface.name = port.name.value
113 1
            interface.address = port.hw_addr.value
114 1
            interface.state = port.state.value
115 1
            interface.features = port.curr
116 1
            interface.config = config
117 1
            interface.set_custom_speed(port.curr_speed.value)
118
        else:
119 1
            interface = Interface(name=port.name.value,
120
                                  address=port.hw_addr.value,
121
                                  port_number=port.port_no.value,
122
                                  switch=switch,
123
                                  state=port.state.value,
124
                                  features=port.curr,
125
                                  speed=port.curr_speed.value,
126
                                  config=config)
127 1
        switch.update_interface(interface)
128 1
        port_event = KytosEvent(name='kytos/of_core.switch.port.created',
129
                                content={
130
                                    'switch': switch.id,
131
                                    'port': port.port_no.value,
132
                                    'port_description': {
133
                                        'alias': port.name.value,
134
                                        'mac': port.hw_addr.value,
135
                                        'state': port.state.value
136
                                        }
137
                                    })
138 1
        controller.buffers.app.put(port_event)
139
140
141 1
def send_echo(controller, switch):
142
    """Send echo request to a datapath.
143
144
    Keep the connection alive through symmetric echoes.
145
    """
146 1
    echo = EchoRequest(data=b'kytosd_13')
147 1
    emit_message_out(controller, switch.connection, echo)
148
149
150 1
def send_set_config(controller, switch):
151
    """Send a SetConfig message after the OpenFlow handshake."""
152 1
    set_config = SetConfig()
153 1
    set_config.flags = ConfigFlag.OFPC_FRAG_NORMAL
154 1
    set_config.miss_send_len = ControllerMaxLen.OFPCML_NO_BUFFER
155 1
    emit_message_out(controller, switch.connection, set_config)
156
157
158 1
def say_hello(controller, connection):
159
    """Send back a Hello packet with the same version as the switch."""
160 1
    hello = Hello()
161 1
    emit_message_out(controller, connection, hello)
162
163
164 1
def mask_to_bytes(mask, size):
165
    """Return the mask in bytes."""
166
    bits = 0
167
    for i in range(size-mask, size):
168
        bits |= (1 << i)
169
    tobytes = bits.to_bytes(size//8, 'big')
170
    return tobytes
171
172
173 1
def bytes_to_mask(tobytes, size):
174
    """Return the mask in string."""
175
    int_mask = int.from_bytes(tobytes, 'big')
176
    strbits = format(int_mask, 'b')
177
    netmask = 0
178
    for i in range(size):
179
        if strbits[i] == '1':
180
            netmask += 1
181
        else:
182
            break
183
    return netmask
184