def __init__(self, *args, **kwargs): super(VRRPInterfaceMonitorNetworkDevice, self).__init__(*args, **kwargs) self.__is_active = True config = self.config if config.is_ipv6: family = socket.AF_INET6 ether_type = ether.ETH_TYPE_IPV6 mac_address = vrrp.vrrp_ipv6_src_mac_address(config.vrid) else: family = socket.AF_INET ether_type = ether.ETH_TYPE_IP mac_address = vrrp.vrrp_ipv4_src_mac_address(config.vrid) # socket module doesn't define IPPROTO_VRRP self.ip_socket = socket.socket(family, socket.SOCK_RAW, inet.IPPROTO_VRRP) self.packet_socket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(ether_type)) self.packet_socket.bind((self.interface.device_name, ether_type, socket.PACKET_MULTICAST, arp.ARP_HW_TYPE_ETHERNET, addrconv.mac.text_to_bin(mac_address))) self.ifindex = if_nametoindex(self.interface.device_name)
def _drop_match(self, dp): kwargs = {} kwargs['in_port'] = self.interface.port_no kwargs['eth_dst'] = vrrp.vrrp_ipv4_src_mac_address(self.config.vrid) if self.interface.vlan_id is not None: kwargs['vlan_vid'] = self.interface.vlan_id return dp.ofproto_parser.OFPMatch(**kwargs)
def _arp_match(self, dp): kwargs = {} kwargs['in_port'] = self.interface.port_no kwargs['eth_dst'] = mac_lib.BROADCAST_STR kwargs['eth_type'] = ether.ETH_TYPE_ARP if self.interface.vlan_id is not None: kwargs['vlan_vid'] = self.interface.vlan_id kwargs['arp_op'] = arp.ARP_REQUEST kwargs['arp_tpa'] = vrrp.vrrp_ipv4_src_mac_address(self.config.vrid) return dp.ofproto_parser.OFPMatch(**kwargs)
def _garp_packet(self, ip_address): # prepare garp packet src_mac = vrrp.vrrp_ipv4_src_mac_address(self.config.vrid) e = ethernet.ethernet(mac_lib.BROADCAST_STR, src_mac, ether.ETH_TYPE_ARP) a = arp.arp_ip(arp.ARP_REQUEST, src_mac, ip_address, mac_lib.DONTCARE_STR, ip_address) p = packet.Packet() p.add_protocol(e) utils.may_add_vlan(p, self.interface.vlan_id) p.add_protocol(a) p.serialize() return p
def _join_multicast_membership(self, join_leave): config = self.config if config.is_ipv6: mac_address = vrrp.vrrp_ipv6_src_mac_address(config.vrid) else: mac_address = vrrp.vrrp_ipv4_src_mac_address(config.vrid) if join_leave: add_drop = PACKET_ADD_MEMBERSHIP else: add_drop = PACKET_DROP_MEMBERSHIP packet_mreq = struct.pack('IHH8s', self.ifindex, PACKET_MR_MULTICAST, 6, addrconv.mac.text_to_bin(mac_address)) self.packet_socket.setsockopt(SOL_PACKET, add_drop, packet_mreq)
def _arp_reply_packet(self, arp_req_sha, arp_req_spa, arp_req_tpa): if not (arp_req_tpa in self.config.ip_addresses or arp_req_tpa == self.config.primary_ip_address): return None src_mac = vrrp.vrrp_ipv4_src_mac_address(self.config.vrid) e = ethernet.ethernet(arp_req_sha, src_mac, ether.ETH_TYPE_ARP) a = arp.arp_ip(arp.ARP_REPLY, src_mac, arp_req_tpa, arp_req_sha, arp_req_spa) p = packet.Packet() p.add_protocol(e) utils.may_add_vlan(p, self.interface.vlan_id) p.add_protocol(a) p.serialize() self._transmit(p.data)
def _join_multicast_membership(self, join_leave): config = self.config if config.is_ipv6: mac_address = vrrp.vrrp_ipv6_src_mac_address(config.vrid) else: mac_address = vrrp.vrrp_ipv4_src_mac_address(config.vrid) if join_leave: add_drop = PACKET_ADD_MEMBERSHIP else: add_drop = PACKET_DROP_MEMBERSHIP # struct packet_mreq { # int mr_ifindex; # unsigned short mr_type; # unsigned short mr_alen; # unsigned char mr_mr_address[8]; # }; packet_mreq = struct.pack('IHH8s', self.ifindex, PACKET_MR_MULTICAST, 6, addrconv.mac.text_to_bin(mac_address)) self.packet_socket.setsockopt(SOL_PACKET, add_drop, packet_mreq)
def _arp_process(self, data): dst_mac = vrrp.vrrp_ipv4_src_mac_address(self.config.vrid) arp_sha = None arp_spa = None arp_tpa = None p = packet.Packet(data) for proto in p.protocols: if isinstance(proto, ethernet.ethernet): if proto.dst not in (mac_lib.BROADCAST_STR, dst_mac): return None ethertype = proto.ethertype if not ((self.interface.vlan_id is None and ethertype == ether.ETH_TYPE_ARP) or (self.interface.vlan_id is not None and ethertype == ether.ETH_TYPE_8021Q)): return None elif isinstance(proto, vlan.vlan): if (proto.vid != self.interface.vlan_id or proto.ethertype != ether.ETH_TYPE_ARP): return None elif isinstance(proto, arp.arp): if (proto.hwtype != arp.ARP_HW_TYPE_ETHERNET or proto.proto != ether.ETH_TYPE_IP or proto.hlen != 6 or proto.plen != 4 or proto.opcode != arp.ARP_REQUEST or proto.dst_mac != dst_mac): return None arp_sha = proto.src_mac arp_spa = proto.src_ip arp_tpa = proto.dst_ip break if arp_sha is None or arp_spa is None or arp_tpa is None: self.logger.debug('malformed arp request? arp_sha %s arp_spa %s', arp_sha, arp_spa) return None self._arp_reply_packet(arp_sha, arp_spa, arp_tpa)
def _ofp_match(self, ofproto_parser): is_ipv6 = vrrp.is_ipv6(self.config.ip_addresses[0]) kwargs = {} kwargs['in_port'] = self.interface.port_no if is_ipv6: kwargs['eth_dst'] = vrrp.VRRP_IPV6_DST_MAC_ADDRESS kwargs['eth_src'] = \ vrrp.vrrp_ipv6_src_mac_address(self.config.vrid) kwargs['eth_type'] = ether.ETH_TYPE_IPV6 kwargs['ipv6_dst'] = vrrp.VRRP_IPV6_DST_ADDRESS else: kwargs['eth_dst'] = vrrp.VRRP_IPV4_DST_MAC_ADDRESS kwargs['eth_src'] = \ vrrp.vrrp_ipv4_src_mac_address(self.config.vrid) kwargs['eth_type'] = ether.ETH_TYPE_IP kwargs['ipv4_dst'] = vrrp.VRRP_IPV4_DST_ADDRESS if self.interface.vlan_id is not None: kwargs['vlan_vid'] = self.interface.vlan_id kwargs['ip_proto'] = inet.IPPROTO_VRRP # OF1.2 doesn't support TTL match. # It needs to be checked by packet in handler return ofproto_parser.OFPMatch(**kwargs)