| 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 |  |  |     multipart_request = MultipartRequest() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     multipart_request.multipart_type = MultipartType.OFPMP_FLOW | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |     multipart_request.body = FlowStatsRequest() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     emit_message_out(controller, switch.connection, multipart_request) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |     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 |  |  |     multipart_request = MultipartRequest() | 
            
                                                                        
                            
            
                                    
            
            
                | 45 |  |  |     multipart_request.multipart_type = MultipartType.OFPMP_DESC | 
            
                                                                        
                            
            
                                    
            
            
                | 46 |  |  |     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 |  |  |     port_request = MultipartRequest() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     port_request.multipart_type = MultipartType.OFPMP_PORT_DESC | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |     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 |  |  |     connection = event.source | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |     features_reply = event.content['message'] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |     dpid = features_reply.datapath_id.value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |     switch = controller.get_switch_or_create(dpid=dpid, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |                                              connection=connection) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |     send_port_request(controller, connection) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     switch.update_features(features_reply) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |     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 |  |  |     for port in port_list: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |         interface = switch.get_interface_by_port_no(port.port_no.value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |         if interface: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |             interface.name = port.name.value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |             interface.address = port.hw_addr.value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |             interface.state = port.state.value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |             interface.features = port.curr | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |             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 |  |  |         switch.update_interface(interface) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         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 |  |  |         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 |  |  |     echo = EchoRequest(data=b'kytosd_13') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |     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 |  |  |     set_config = SetConfig() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |     set_config.flags = ConfigFlag.OFPC_FRAG_NORMAL | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |     set_config.miss_send_len = ControllerMaxLen.OFPCML_NO_BUFFER | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |     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 |  |  |     hello = Hello() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |     emit_message_out(controller, connection, hello) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  | 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 |  |  | def bytes_to_mask(tobytes, size): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |     """Return the mask in string.""" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |     int_mask = int.from_bytes(tobytes, 'big') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |     strbits = format(int_mask, 'b') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |     netmask = 0 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |     for i in range(size): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |         if strbits[i] == '1': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |             netmask += 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |             break | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 151 |  |  |     return netmask | 
            
                                                        
            
                                    
            
            
                | 152 |  |  |  |