build.v0x04.utils.mask_to_bytes()   A
last analyzed

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.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
        event_name = 'kytos/of_core.switch.interface.created'
129 1
        interface_event = KytosEvent(name=event_name,
130
                                     content={'interface': interface})
131 1
        port_event = KytosEvent(name='kytos/of_core.switch.port.created',
132
                                content={
133
                                    'switch': switch.id,
134
                                    'port': port.port_no.value,
135
                                    'port_description': {
136
                                        'alias': port.name.value,
137
                                        'mac': port.hw_addr.value,
138
                                        'state': port.state.value
139
                                        }
140
                                    })
141 1
        controller.buffers.app.put(port_event)
142 1
        controller.buffers.app.put(interface_event)
143
144
145 1
def send_echo(controller, switch):
146
    """Send echo request to a datapath.
147
148
    Keep the connection alive through symmetric echoes.
149
    """
150 1
    echo = EchoRequest(data=b'kytosd_13')
151 1
    emit_message_out(controller, switch.connection, echo)
152
153
154 1
def send_set_config(controller, switch):
155
    """Send a SetConfig message after the OpenFlow handshake."""
156 1
    set_config = SetConfig()
157 1
    set_config.flags = ConfigFlag.OFPC_FRAG_NORMAL
158 1
    set_config.miss_send_len = ControllerMaxLen.OFPCML_NO_BUFFER
159 1
    emit_message_out(controller, switch.connection, set_config)
160
161
162 1
def say_hello(controller, connection):
163
    """Send back a Hello packet with the same version as the switch."""
164 1
    hello = Hello()
165 1
    emit_message_out(controller, connection, hello)
166
167
168 1
def mask_to_bytes(mask, size):
169
    """Return the mask in bytes."""
170
    bits = 0
171
    for i in range(size-mask, size):
172
        bits |= (1 << i)
173
    tobytes = bits.to_bytes(size//8, 'big')
174
    return tobytes
175
176
177 1
def bytes_to_mask(tobytes, size):
178
    """Return the mask in string."""
179
    int_mask = int.from_bytes(tobytes, 'big')
180
    strbits = format(int_mask, 'b')
181
    netmask = 0
182
    for i in range(size):
183
        if strbits[i] == '1':
184
            netmask += 1
185
        else:
186
            break
187
    return netmask
188