def _handle_open(self, msg): self.peer_as = msg.my_as peer_holdtime = msg.hold_time self.hold_time = min(peer_holdtime, self.hold_time) self.peer_id = msg.bgp_identifier self.peer_capabilities = msg.data for capability in self.peer_capabilities: if isinstance(capability, BGP4.multi_protocol_extension): if capability.addr_family == 1: self._4or6 = 4 elif capability.addr_family == 2: self._4or6 = 6 else: self._4or6 = 0 if isinstance(capability, BGP4.support_4_octets_as_num): self.peer_as = capability.as_num print '4/6:', self._4or6 print 'peer_as:', self.peer_as print 'hold_time:', self.hold_time print 'peer_id:', convert.ipv4_to_str(self.peer_id) print 'capability:', self.peer_capabilities self.send_open_msg() if self.__check_capabilities(self.peer_capabilities): hub.spawn(self.keepalive) self.send_current_route_table() else: self.send_notification_msg()
def _handle_arp(self, msg, pkt, arp_pkt): ''' 1) handles ARP request from hosts, about their gateways; only works in IPv4 since IPv6 uses NDP(ICMPv6); e.g. when a host need to send a packet to the gateway, it will firstly send an ARP to get the MAC address of the gateway 2) handles ARP reply from hosts, and try to send packets currently stored in switch.msg_buffer ''' #print 'arp', arp_pkt if arp_pkt.opcode == arp.ARP_REPLY: self._handle_arp_reply(msg, pkt, arp_pkt) return if arp_pkt.opcode != arp.ARP_REQUEST: return switch = self.dpid_to_switch[msg.datapath.id] in_port_no = msg.in_port req_dst_ip = arp_pkt.dst_ip req_src_ip = arp_pkt.src_ip port = switch.ports[in_port_no] if port.gateway and req_dst_ip != port.gateway.gw_ip: return datapath = msg.datapath reply_src_mac = port.hw_addr ether_layer = self.find_packet(pkt, 'ethernet') e = ethernet.ethernet(dst=ether_layer.src, src=reply_src_mac, ethertype=ether.ETH_TYPE_ARP) a = arp.arp(hwtype=arp.ARP_HW_TYPE_ETHERNET, proto=ether.ETH_TYPE_IP, hlen=6, plen=4, opcode=arp.ARP_REPLY, src_mac=reply_src_mac, src_ip=req_dst_ip, dst_mac=arp_pkt.src_mac, dst_ip=req_src_ip) p = packet.Packet() p.add_protocol(e) p.add_protocol(a) p.serialize() datapath.send_packet_out( in_port=ofproto_v1_0.OFPP_NONE, actions=[datapath.ofproto_parser.OFPActionOutput(in_port_no)], data=p.data) print 'ARP replied:', convert.haddr_to_str(reply_src_mac), \ convert.ipv4_to_str(req_dst_ip)
def _remember_mac_addr(self, switch, packet, _4or6): ''' get ip <-> mac relationship from packets and store them in dict ip_to_mac ''' time_now = time.time() ether_layer = self.find_packet(packet, 'ethernet') if _4or6 == 4: ip_layer = self.find_packet(packet, 'ipv4') if ip_layer == None: ip_layer = self.find_packet(packet, 'arp') ip_layer.src = ip_layer.src_ip print 'ARP from ARP' print 'ARP entry:', convert.haddr_to_str(ether_layer.src), print convert.ipv4_to_str(ip_layer.src) else: ip_layer = self.find_packet(packet, 'ipv6') switch.ip_to_mac[ip_layer.src] = (ether_layer.src, time_now)
def parser(cls, buf, offset): (version, my_as, hold_time, bgp_identifier, opt_para_len) = \ struct.unpack_from(cls._PACK_STR, buf, offset) offset += cls._MIN_LEN bgp_identifier = convert.ipv4_to_str(bgp_identifier) ''' There're two types of packet structure: 1) Optional Parameters Optional Parameter: Capability Capability 1 capability 2 ... Capability n 2) Optional Parameters Optional Parameter: Capability Capability 1 ... Capability n Optional Parameter: Capability Capability ... Optional Parameter: Capability Capability The second one is obselete but should be supported, as defined in RFC 5492 ''' if opt_para_len >= 2: (type_, para_len) = struct.unpack_from('!BB', buf, offset) msg = cls(version, my_as, hold_time, bgp_identifier, opt_para_len, type_, para_len) else: msg = cls(version, my_as, hold_time, bgp_identifier, opt_para_len) return msg msg.data = [] buf = buffer(buf[offset:]) while len(buf) > 0: (type_, para_len) = struct.unpack_from('!BB', buf) sub_buf = buffer(buf[2:para_len + 2]) while len(sub_buf) > 0: code, len_ = struct.unpack_from('!BB', sub_buf) cls_ = cls._CAPABILITY_ADVERTISEMENT.get(code, None) if cls_: msg.data.append(cls_.parser(sub_buf, 0)) sub_buf = buffer(sub_buf[len_ + 2:]) buf = buffer(buf[para_len + 2:]) return msg
def _handle_arp(self, msg, pkt, arp_pkt): ''' 1) handles ARP request from hosts, about their gateways; only works in IPv4 since IPv6 uses NDP(ICMPv6); e.g. when a host need to send a packet to the gateway, it will firstly send an ARP to get the MAC address of the gateway 2) handles ARP reply from hosts, and try to send packets currently stored in switch.msg_buffer ''' #print 'arp', arp_pkt if arp_pkt.opcode == arp.ARP_REPLY: self._handle_arp_reply(msg, pkt, arp_pkt) return if arp_pkt.opcode != arp.ARP_REQUEST: return switch = self.dpid_to_switch[msg.datapath.id] in_port_no = msg.in_port req_dst_ip = arp_pkt.dst_ip req_src_ip = arp_pkt.src_ip port = switch.ports[in_port_no] if port.gateway and req_dst_ip != port.gateway.gw_ip: return datapath = msg.datapath reply_src_mac = port.hw_addr ether_layer = self.find_packet(pkt, 'ethernet') e = ethernet.ethernet(dst = ether_layer.src, src = reply_src_mac, ethertype = ether.ETH_TYPE_ARP) a = arp.arp(hwtype = arp.ARP_HW_TYPE_ETHERNET, proto = ether.ETH_TYPE_IP, hlen = 6, plen = 4, opcode = arp.ARP_REPLY, src_mac = reply_src_mac, src_ip = req_dst_ip, dst_mac = arp_pkt.src_mac, dst_ip = req_src_ip) p = packet.Packet() p.add_protocol(e) p.add_protocol(a) p.serialize() datapath.send_packet_out(in_port = ofproto_v1_0.OFPP_NONE, actions = [datapath.ofproto_parser.OFPActionOutput(in_port_no)], data = p.data) print 'ARP replied:', convert.haddr_to_str(reply_src_mac), \ convert.ipv4_to_str(req_dst_ip)
def parser(cls, buf, offset): (flag, code) = struct.unpack_from('!BB', buf, offset) if ((flag & 0x10) == 0x10): cls._PACK_STR = '!BBH' cls._MIN_LEN = struct.calcsize(cls._PACK_STR) else: cls._PACK_STR = '!BBB' cls._MIN_LEN = struct.calcsize(cls._PACK_STR) (flag, code, length) = struct.unpack_from(cls._PACK_STR, buf, offset) offset += cls._MIN_LEN if length >= 4: (addr_family, sub_addr_family, next_hop_len) = struct.unpack_from('!HBB', buf, offset) offset += 4 next_hop = [] if next_hop_len == 4: (temp_next_hop, ) = struct.unpack_from('!I', buf, offset) offset += 4 next_hop.append(convert.ipv4_to_str(temp_next_hop)) else: if next_hop_len / 16 != 0: for i in range(next_hop_len / 16): (temp_next_hop, ) = struct.unpack_from('!16s', buf, offset) offset += 16 next_hop.append(convert.bin_to_ipv6(temp_next_hop)) if len(buf) > offset: # as SNPA is obselete, jump over this field (num_of_snpas, ) = struct.unpack_from('!B', buf, offset) offset += 1 if num_of_snpas != 0: for i in range(num_of_snpas): (len_of_snap, ) = struct.unpack_from('!B', buf, offset) offset += 1 + len_of_snap # the "5" includes AF(2), SAFI(1), len of next_hop_len(1), # and reserved(1) nlri_len = length - 5 - next_hop_len # we could safely assume it's IPv6 here nlri = NLRI.parser(buf, offset, nlri_len, 6) msg = cls(flag, code, length, addr_family, sub_addr_family, next_hop_len, next_hop, nlri) return msg
def __str__(self): return 'Gateway<name=%s,gw_ip=%s,gw_ipv6=%s,port_num=%s,\ prefixLen=%s,ipv6prefixlen=%s,border=%s>' % ( self.port_name, convert.ipv4_to_str(self.gw_ip), convert.bin_to_ipv6(self.gw_ipv6), self.port_num, self.prefixlen, self.ipv6prefixlen, self.border)
def get_flow_stats(dp, waiters): rule = nx_match.ClsRule() stats = dp.ofproto_parser.NXFlowStatsRequest(datapath = dp, flags = 0, out_port = dp.ofproto.OFPP_NONE, table_id = 0xff) msgs = [] send_stats_request(dp, stats, waiters, msgs) flows =[] for msg in msgs: for body in msg.body: actions = actions_to_str(body.actions) s = {'cookie':hex(body.cookie), 'duration': str(body.duration_sec) +'.'+ str(body.duration_nsec), 'table_id':body.table_id, 'n_packets':body.packet_count, 'n_bytes':body.byte_count, 'idle_age':body.idle_age, 'priority':body.priority, 'nx_match':[], 'actions':actions } _dict = {} for field in body.fields: if field.nxm_header == ofproto_v1_0.NXM_OF_IN_PORT: _dict['in_port'] = hex(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_ETH_SRC: _dict['dl_src'] = haddr_to_str(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_ETH_DST: _dict['dl_dst'] = haddr_to_str(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_ETH_TYPE: _dict['dl_type'] = hex(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_IP_SRC: _dict['nw_src'] = convert.ipv4_to_str(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_IP_SRC_W: _dict['nw_src'] = convert.ipv4_to_str(field.value) _dict['nw_src_masked'] = convert.bin_to_ipv4_prefix(field.mask) elif field.nxm_header == ofproto_v1_0.NXM_OF_IP_DST: _dict['nw_dst'] = convert.ipv4_to_str(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_IP_DST_W: _dict['nw_dst'] = convert.ipv4_to_str(field.value) _dict['nw_dst_masked'] = convert.ipv4_to_str(field.mask) elif field.nxm_header == ofproto_v1_0.NXM_NX_TUN_ID : _dict['tun_id'] = hex(field.value) elif field.nxm_header == ofproto_v1_0.NXM_OF_TCP_SRC: _dict['tp_src'] = field.value elif field.nxm_header == ofproto_v1_0.NXM_OF_TCP_DST: _dict['tp_dst'] = field.value elif field.nxm_header == ofproto_v1_0.NXM_OF_IP_PROTO: _dict['nw_proto'] = field.value elif field.nxm_header == ofproto_v1_0.NXM_NX_IPV6_SRC: #print '****',field.value _dict['ipv6_src'] = ipv6_add_to_str(field.value) elif field.nxm_header == ofproto_v1_0.NXM_NX_IPV6_SRC_W: _dict['ipv6_src'] = ipv6_add_to_str(field.value) _dict['ipv6_src_masked'] = convert.arg_list_to_ipv6_prefix(field.mask) elif field.nxm_header == ofproto_v1_0.NXM_NX_IPV6_DST: _dict['ipv6_dst'] = ipv6_add_to_str(field.value) elif field.nxm_header == ofproto_v1_0.NXM_NX_IPV6_DST_W: _dict['ipv6_dst'] = ipv6_add_to_str(field.value) _dict['ipv6_dst_masked'] = convert.arg_list_to_ipv6_prefix(field.mask) else: pass """ try: _dict['value'] = hex(field.value) except: _dict['value'] = ''.join(c for c in field.value) """ s['nx_match'].append(_dict) flows.append(s) flows = {str(dp.id): flows} return flows
def __str__(self): ans = 'Next hop: ' ans += convert.ipv4_to_str(self._next_hop) return '<%s>' % ans
def __str__(self): return 'Gateway<name=%s,gw_ip=%s,gw_ipv6=%s,port_num=%s,\ prefixLen=%s,ipv6prefixlen=%s,border=%s>' % ( self.port_name, convert.ipv4_to_str( self.gw_ip), convert.bin_to_ipv6(self.gw_ipv6), self.port_num, self.prefixlen, self.ipv6prefixlen, self.border)