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