def compare_bpdu_info(my_priority, my_times, rcv_priority, rcv_times): """ Check received BPDU is superior to currently held BPDU by the following comparison. - root bridge ID value - root path cost - designated bridge ID value - designated port ID value - times """ if my_priority is None: result = SUPERIOR else: result = Stp._cmp_value(rcv_priority.root_id.value, my_priority.root_id.value) if not result: result = Stp.compare_root_path( rcv_priority.root_path_cost, my_priority.root_path_cost, rcv_priority.designated_bridge_id.value, my_priority.designated_bridge_id.value, rcv_priority.designated_port_id.value, my_priority.designated_port_id.value) if not result: result1 = Stp._cmp_value( rcv_priority.designated_bridge_id.value, mac.haddr_to_int( my_priority.designated_bridge_id.mac_addr)) result2 = Stp._cmp_value( rcv_priority.designated_port_id.value, my_priority.designated_port_id.port_no) if not result1 and not result2: result = SUPERIOR else: result = Stp._cmp_obj(rcv_times, my_times) return result
def generate_arp_reply(self, dst_ip, dst_mac): self.logger.info("Generating ARP Reply Packet") self.logger.info("ARP request client ip: " + dst_ip + ", client mac: " + dst_mac) arp_target_ip = dst_ip # the sender ip arp_target_mac = dst_mac # the sender mac # Making the load balancer IP as source IP src_ip = self.VIRTUAL_IP if haddr_to_int(arp_target_mac) % 2 == 1: src_mac = self.SERVER1_MAC else: src_mac = self.SERVER2_MAC self.logger.info("Selected server MAC: " + src_mac) pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet(dst=dst_mac, src=src_mac, ethertype=ether_types.ETH_TYPE_ARP)) pkt.add_protocol( arp.arp(opcode=arp.ARP_REPLY, src_mac=src_mac, src_ip=src_ip, dst_mac=arp_target_mac, dst_ip=arp_target_ip)) pkt.serialize() self.logger.info("Done with processing the ARP reply packet") return pkt
def generate_arp_reply(self, dst_ip, dst_mac): """ An ARP reply is generated in the controller code with the source address as load balancers and destination as client address and passed to the switch which transmits it back to the client. For the future, a flow is created (load balancer to client) and inserted in the switch that modifies the packet header and changes the destination MAC to that of the client and source MAC to load balancers. So, further ARP requests from the same client on that in port will automatically be replied to by the switch at line rate speed. To the client which started the connection it would look like the server (load balancer) has replied with its MAC. For successive ARP connections: After the first encounter, the controller inserts the flow table entries into the switch so the switch would match the packet with a flow and according to priority take the corresponding action at line rate speed just like a legacy switch. """ self.logger.info("Generating ARP Reply Packet") self.logger.info("ARP request client ip: " + dst_ip + ", client mac: " + dst_mac) arp_target_ip = dst_ip # the sender ip arp_target_mac = dst_mac # the sender mac # Making the load balancer IP as source IP src_ip = self.VIRTUAL_IP if haddr_to_int(arp_target_mac) % 2 == 1: src_mac = self.SERVER1_MAC else: src_mac = self.SERVER2_MAC self.logger.info("Selected server MAC: " + src_mac) pkt = packet.Packet() pkt.add_protocol( ethernet.ethernet(dst=dst_mac, src=src_mac, ethertype=ether_types.ETH_TYPE_ARP)) pkt.add_protocol( arp.arp(opcode=arp.ARP_REPLY, src_mac=src_mac, src_ip=src_ip, dst_mac=arp_target_mac, dst_ip=arp_target_ip)) pkt.serialize() self.logger.info("Done with processing the ARP reply packet") return pkt
def get_expected_dest_address(self, src_mac): return Server(self.server_ip1, self.server_mac1, 1) if haddr_to_int(src_mac) % 2 == 1 else Server( self.server_ip2, self.server_mac2, 2)
def match(flow, pkt, in_port, ofp, in_phy_port=None): """ Args: flow: pkt: in_port: ofp: in_phy_port: Returns: """ eth = pkt[0] vlan = pkt[1] print flow if 'in_port' in flow: if flow['in_port'] != in_port: return False if 'in_phy_port' in flow: if flow['in_phy_port'] != in_phy_port: return False if 'eth_dst' in flow: eth_dst = flow['eth_dst'] if isinstance(eth_dst, tuple): edst, mask = map(mac.haddr_to_int, eth_dst) if edst & mask != mac.haddr_to_int(eth.dst) & mask: return False else: if eth_dst != eth.dst: return False if 'eth_src' in flow: eth_src = flow['eth_src'] if isinstance(eth_src, tuple): esrc, mask = map(mac.haddr_to_int, eth_src) if esrc & mask != mac.haddr_to_int(eth.src) & mask: return False else: if eth_src != eth.src: return False if 'eth_type' in flow: if flow['eth_type'] != vlan.ethertype: return False def test_vid(vid): if vid == ofp.OFPVID_NONE and vlan.vid: return False if vid != vlan.vid | ofp.OFPVID_PRESENT: return False return True if 'vlan_vid' in flow: vlan_vid = flow['vlan_vid'] if isinstance(vlan_vid, tuple): vid, mask = vlan_vid if vid == mask == ofp.OFPVID_PRESENT and not vlan.vid: return False else: test_vid(vid) else: vid = vlan_vid if not test_vid(vid): return False if 'vlan_pcp' in flow: if flow['vlan_pcp'] != vlan.vid: return False ip_dscp = None ip_ecn = None ip_proto = None if vlan.ethertype == 0x0800: ip4 = pkt[2] tp = pkt[3] ip_dscp = ip4.tos >> 2 ip_ecn = ip4.tos & 0x03 ip_proto = ip4.proto if 'ipv4_src' in flow: ipv4_src = flow['ipv4_src'] if isinstance(ipv4_src, tuple): ipsrc, mask = map(ip.ipv4_to_int, ipv4_src) if ipsrc & mask != ip.ipv4_to_int(ip4.src) & mask: return False else: if ipv4_src != ip4.src: return False if 'ipv4_dst' in flow: ipv4_dst = flow['ipv4_dst'] if isinstance(ipv4_dst, tuple): ipsrc, mask = map(ip.ipv4_to_int, ipv4_dst) if ipsrc & mask != ip.ipv4_to_int(ip4.dst) & mask: return False else: if ipv4_dst != ip4.dst: return False if vlan.ethertype == 0x86dd: ip6 = pkt[2] tp = pkt[3] ip_dscp = ip6.traffic_class >> 2 ip_ecn = ip6.traffic_class & 0x03 ip_proto = ip6.nxt if 'ipv6_src' in flow: ipv6_src = flow['ipv6_src'] if isinstance(ipv6_src, tuple): ipsrc, mask = map(ip.ipv6_to_int, ipv6_src) if ipsrc & mask != ip.ipv6_to_int(ip6.src) & mask: return False else: if ipv6_src != ip6.src: return False if 'ipv6_dst' in flow: ipv6_dst = flow['ipv64_dst'] if isinstance(ipv6_dst, tuple): ipsrc, mask = map(ip.ipv6_to_int, ipv6_dst) if ipsrc & mask != ip.ipv6_to_int(ip6.dst) & mask: return False else: if ipv6_dst != ip6.dst: return False if 'ip_dscp' in flow and ip_dscp is not None: if flow['ip_dscp'] != ip_dscp: return False if 'ip_ecn' in flow and ip_ecn is not None: if flow['ip_ecn'] != ip_ecn: return False if 'ip_proto' in flow and ip_proto is not None: if flow['ip_proto'] != ip_proto: return False if ip_proto == 6: # TCP if 'tcp_src' in flow: if flow['tcp_src'] != tp.src_port: return False if 'tcp_dst' in flow: if flow['tcp_dst'] != tp.dst_port: return False if ip_proto == 17: # UDP if 'udp_src' in flow: if flow['udp_src'] != tp.src_port: return False if 'udp_dst' in flow: if flow['udp_dst'] != tp.dst_port: return False if ip_proto == 132: # SCTP if 'sctp_src' in flow: if flow['sctp_src'] != tp.src_port: return False if 'sctp_dst' in flow: if flow['sctp_dst'] != tp.dst_port: return False return True
def get_expected_dest_address(self, src_mac): return self.H1_ip if haddr_to_int(src_mac) % 2 == 1 else self.H2_ip