Passed
Push — master ( e18d69...5f36f8 )
by Humberto
02:10
created

build.v0x04.utils.mask_to_bytes()   A

Complexity

Conditions 2

Size

Total Lines 7
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 4.3145

Importance

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