def add_inputs(self, inputs): aux = [] count_good = 0 count_bad = 0 if isinstance(inputs, type({})): aux = [inputs["packet"]] elif isinstance(inputs, type([])): aux = map(lambda x: x["packet"], inputs) else: utils.crash("Unknown inputs provided: %s" % inputs) inputs = aux for p in inputs: if self.filter_src_mac: # sanity checks on the input packets macs = self.state.model.getClientMacAddresses() if p["src"] not in macs or p["dst"] not in macs or p[ "src"] != self.mymac or p["src"] == p["dst"]: count_bad += 1 continue ep = ethernet.ethernet("se.packet%d" % self.input_counter) ep.src = MacAddress(p["src"]) ep.dst = MacAddress(p["dst"]) ep.parsed = p["parsed"] ep.next = p["next"] ep.type = p["type"] ep.arr = p["arr"] self.input_counter += 1 count_good += 1 self.pkts[ep.name] = ep self.enableAction("send_packet", ep.name) self.log.info("Accepted %d new packets, discarded %d invalid packets" % (count_good, count_bad))
def test1(dpid, inport, reason, len, bufid, packet): flow = {} #extract_flow(packet) #flow[core.IN_PORT] = inport flow[core.DL_SRC] = MacAddress((0x00, 0x00, 0x00, 0x00, 0x01, 0x00)) flow[core.NW_SRC] = IpAddress("128.0.0.11") flow[core.DL_TYPE] = 2048 actions = [[openflow.OFPAT_OUTPUT, [0, 1]]] flow1 = {} flow1[core.DL_SRC] = MacAddress((0x00, 0x00, 0x00, 0x00, 0x01, 0x00)) flow1[core.NW_DST] = IpAddress("128.0.0.12") flow1[core.NW_SRC] = IpAddress("128.0.0.11") flow1[core.DL_TYPE] = 2048 actions1 = [] #[[openflow.OFPAT_OUTPUT, [0, 0]]] #inst.install_datapath_flow(dpid, flow1, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions1, None, 1000, inport, packet.arr) inst.install_datapath_flow(dpid, flow, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.17") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.18") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.19") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.20") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.21") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.22") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.23") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr) inst.install_datapath_flow(dpid, { core.DL_TYPE: 2048, core.NW_DST: IpAddress("128.0.0.24") }, openflow.OFP_FLOW_PERMANENT, openflow.OFP_FLOW_PERMANENT, actions, None, 500, inport, packet.arr)
def __init__(self, name="noname"): """ name is the name of ethernet packet """ self.name = name self.src = MacAddress() self.dst = MacAddress() self.type = ethernet.ETH_TYPE self.arr = None self.packet_id = None # used by invariants self.annotation = [] # used by invariants self.fault_injection = [] # just for debugging, to help tracking packets around
def arp_query(self, ip): name = "arp_query" + str(ip) packet = self.build_arp_packet(arp.arp.REQUEST, MacAddress("0:0:0:0:0:0"), ip) packet = self.build_ethernet_packet(name, ethernet.ETHER_BROADCAST, packet, ARP_TYPE) self.sendPacket(packet, 0) return True
def send_packet(self, dst_mac, dst_ip): flow_id = 1 dest_tcpport = 20 pkt = self.build_tcp_packet(80, dest_tcpport, tcp.tcp.SYN, flow_id, 0, 0) pkt = self.build_ipv4_packet(ipv4.ipv4.TCP_PROTOCOL, IpAddress(dst_ip), pkt) pkt = self.build_ethernet_packet("tcpsyn", MacAddress(dst_mac), pkt, ethernet.ethernet.IP_TYPE) self.sendPacket(pkt, 0) return True
def __init__(self, name, mymac=(0, 0, 0, 0, 0, 0), dstmac=(0, 0, 0, 0, 0, 0), pkts=1, sequential=False): Host.__init__(self, name, mymac, "10.0.0.1") self.dstmac = MacAddress(dstmac) self.pkts = pkts self.received_pkt_count = 0 self.sequential_packet_id = 1 self.sequential = sequential
def packet_received_cb(self, model, receiver, packet, port): if receiver.name == "ctrl": return if packet.dst != MacAddress( "ff:ff:ff:ff:ff:ff") and receiver.mymac != packet.dst: return if packet.packet_id == None: utils.crash("packet with no packet_id: %s" % packet) if not packet.packet_id in self.packet_store: utils.crash("packet received but never sent: %s" % packet) if self.packet_store[packet.packet_id][ 1] > 0: # if there was flooding, packet may arrive more times than it was sent self.packet_store[packet.packet_id][1] -= 1 log.debug("received packet: %s, %d" % (packet.name, self.packet_store[packet.packet_id][1]))
def packet_received_cb(self, model, receiver, packet, port): log.debug("received packet: %s" % packet) if packet.name == "replier.mobility_inform": # information about move is distributed from this point # in time self.in_move = False if packet.packet_id == None: utils.crash("packet with no packet_id: %s" % packet) if not packet.packet_id in self.packet_store: # we are not tracking this packet return if packet.dst != MacAddress( "ff:ff:ff:ff:ff:ff") and receiver.mymac != packet.dst: return if self.packet_store[packet.packet_id][ 1] > 0: # if there was flooding, a packet may arrive more times than it was sent self.packet_store[packet.packet_id][1] -= 1
class ethernet(packet_base): # Ethernet types ETH_TYPE = 1535 # (0x05ff) IP_TYPE = 2048 ARP_TYPE = 2054 RARP_TYPE = 32821 VLAN_TYPE = 33024 LLDP_TYPE = 35020 PAE_TYPE = 34958 def __init__(self, name="noname"): """ name is the name of ethernet packet """ self.name = name self.src = MacAddress() self.dst = MacAddress() self.type = ethernet.ETH_TYPE self.arr = None self.packet_id = None # used by invariants self.annotation = [] # used by invariants self.fault_injection = [] # just for debugging, to help tracking packets around def __str__(self): return self.__repr__() def __repr__(self): if self.next != None: payload = " <- " + repr(self.next) else: payload = "" return "eth: " + str((self.name, self.packet_id, self.src, self.dst, self.type, self.fault_injection)) + payload def __ne__(self, other): if not isinstance(other, ethernet): return True else: return not(self.parsed == other.parsed and self.src == other.src and self.dst == other.dst and self.type == other.type and self.arr == other.arr and self.next == other.next) def __eq__(self, other): if not isinstance(other, ethernet): return False else: return self.parsed == other.parsed and self.src == other.src and self.dst == other.dst and self.type == other.type and self.arr == other.arr and self.next == other.next def __lt__(self, other): return self.name < other.name def __hash__(self): raise NotImplementedError ser = cPickle.dumps(self) return hash(ser) def dump_equivalent_state(self): filtered_dict = {} filtered_dict["name"] = utils.copy_state(self.name) filtered_dict["annotation"] = utils.copy_state(self.annotation) # filtered_dict["packet_id"] = None # filtered_dict["fault_injection"] = False filtered_dict["src"] = utils.copy_state(self.src) filtered_dict["dst"] = utils.copy_state(self.dst) filtered_dict["type"] = utils.copy_state(self.type) if self.next != None: filtered_dict["next"] = utils.copy_state(self.next) return filtered_dict def tostring(self): return self def copy(self): cpy = ethernet() cpy.name = self.name cpy.type = self.type cpy.arr = self.arr cpy.src = self.src.copy() cpy.dst = self.dst.copy() cpy.packet_id = self.packet_id cpy.annotation = list(self.annotation) cpy.fault_injection = self.fault_injection[:] if self.next != None: cpy.set_payload(self.next.copy()) return cpy def toScapy(self): from scapy.layers.l2 import Ether from scapy.packet import Padding src = str(self.src) dst = str(self.dst) ptype = self.type name = self.name pid = self.packet_id #TODO: annotations? #mydata = struct.pack('!%ds%ds' % (len(self.packet_id), len(self.name)), self.packet_id, self.name) mydata = str(self.packet_id) + str(self.name) p = Ether(src = src, dst = dst, type = ptype) if self.next is None: return p, mydata elif isinstance(self.next, packet_base): p2, data = self.next.toScapy() if data is not None: mydata = mydata + data return p/p2, Padding(mydata) elif isinstance(self.next, str): return p, mydata + self.next
def __init__(self, name, mymac, myip): Node.__init__(self, name, 1) self.mymac = MacAddress(mymac) self.myip = IpAddress(myip) self.arp_table = {}
class Host(Node): def __init__(self, name, mymac, myip): Node.__init__(self, name, 1) self.mymac = MacAddress(mymac) self.myip = IpAddress(myip) self.arp_table = {} def start(self, model_checker): Node.start(self, model_checker) def build_ethernet_packet(self, name, dst, payload, type): eth = ethernet.ethernet(name) eth.packet_id = self.genPacketID() eth.set_payload(payload) if type != 0: eth.type = type eth.src = self.mymac.copy() eth.dst = dst.copy() return eth def build_ipv4_packet(self, protocol, dst, payload): ippkt = ipv4.ipv4() ippkt.protocol = protocol ippkt.srcip = self.myip.copy() ippkt.dstip = dst.copy() ippkt.set_payload(payload) return ippkt def build_arp_packet(self, opcode, hwdst, protodst): arppkt = arp.arp() arppkt.protosrc = self.myip.copy() arppkt.protodst = protodst.copy() arppkt.hwsrc = self.mymac.copy() arppkt.opcode = opcode return arppkt def build_tcp_packet(self, srcport, dstport, flags, flow_id, seq, ack): pkt = tcp.tcp() pkt.srcport = srcport pkt.dstport = dstport pkt.flags = flags pkt.seq = seq pkt.ack = ack pkt.flow_id = flow_id return pkt def manage_arp_packet(self, arp_pkt): """ RFC 826 without support for different protocol types """ # import pdb; pdb.set_trace() if arp_pkt.prototype != arp.arp.PROTO_TYPE_IP: return merge_flag = False if self.arp_table.has_key(arp_pkt.hwsrc): self.log.debug("Adding %s to ARP table" % str((arp_pkt.hwsrc, arp_pkt.protosrc))) self.arp_table[arp_pkt.hwsrc] = arp_pkt.protosrc merge_flag = True if self.myip == arp_pkt.protodst: if not merge_flag: self.log.debug("Adding %s to ARP table" % str((arp_pkt.hwsrc, arp_pkt.protosrc))) self.arp_table[arp_pkt.hwsrc] = arp_pkt.protosrc if arp_pkt.opcode == arp.arp.REQUEST: reply = self.build_arp_packet(arp.arp.REPLY, arp_pkt.hwsrc, arp_pkt.protosrc) reply = self.build_ethernet_packet("arp_reply", arp_pkt.hwsrc, reply, ARP_TYPE) self.sendPacket(reply, 0) def arp_query(self, ip): name = "arp_query" + str(ip) packet = self.build_arp_packet(arp.arp.REQUEST, MacAddress("0:0:0:0:0:0"), ip) packet = self.build_ethernet_packet(name, ethernet.ETHER_BROADCAST, packet, ARP_TYPE) self.sendPacket(packet, 0) return True def ip2mac(self, ip): destmac = None for mac in self.arp_table: if self.arp_table[mac] == ip: destmac = mac break if destmac != None: return destmac else: # We need to do an ARP query self.log.info("Issuing ARP Request for %s" % ip) self.arp_query(ip) return None def process_packet(self): raise NotImplementedError @abc.abstractmethod def dump_equivalent_state(self): filtered_dict = Node.dump_equivalent_state(self) filtered_dict["arp_table"] = utils.copy_state(self.arp_table) return filtered_dict
def createMatch(attrs): m = ofp_match() wildcards = 0 num_entries = 0 if attrs.has_key(core.IN_PORT): m.in_port = attrs[core.IN_PORT] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_IN_PORT if attrs.has_key(core.DL_VLAN): m.dl_vlan = attrs[core.DL_VLAN] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_DL_VLAN if attrs.has_key(core.DL_VLAN_PCP): m.dl_vlan_pcp = attrs[core.DL_VLAN_PCP] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_DL_VLAN_PCP if attrs.has_key(core.DL_SRC): v = MacAddress(attrs[core.DL_SRC]) for i in range(0, 6): m.dl_src[i] = v.data[i] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_DL_SRC if attrs.has_key(core.DL_DST): v = MacAddress(attrs[core.DL_DST]) for i in range(0, 6): m.dl_dst[i] = v.data[i] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_DL_DST if attrs.has_key(core.DL_TYPE): m.dl_type = attrs[core.DL_TYPE] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_DL_TYPE if attrs.has_key(core.NW_SRC): if isinstance(attrs[core.NW_SRC], int): m.nw_src = attrs[core.NW_SRC] else: v = IpAddress(attrs[core.NW_SRC]) m.nw_src = v.toint() num_entries += 1 if attrs.has_key(core.NW_SRC_N_WILD): n_wild = attrs[core.NW_SRC_N_WILD] if n_wild > 31: wildcards |= openflow.OFPFW_NW_SRC_MASK elif n_wild >= 0: wildcards |= n_wild << openflow.OFPFW_NW_SRC_SHIFT else: return None num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_NW_SRC_MASK if attrs.has_key(core.NW_DST): if isinstance(attrs[core.NW_DST], int): m.nw_dst = attrs[core.NW_DST] else: v = IpAddress(attrs[core.NW_DST]) m.nw_dst = v.toint() num_entries += 1 if attrs.has_key(core.NW_DST_N_WILD): n_wild = attrs[core.NW_DST_N_WILD] if n_wild > 31: wildcards |= openflow.OFPFW_NW_DST_MASK elif n_wild >= 0: wildcards |= n_wild << openflow.OFPFW_NW_DST_SHIFT else: return None num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_NW_DST_MASK if attrs.has_key(core.NW_PROTO): m.nw_proto = attrs[core.NW_PROTO] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_NW_PROTO if attrs.has_key(core.TP_SRC): m.tp_src = attrs[core.TP_SRC] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_TP_SRC if attrs.has_key(core.TP_DST): m.tp_dst = attrs[core.TP_DST] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_TP_DST if attrs.has_key(core.NW_TOS): m.nw_tos = attrs[core.NW_TOS] num_entries += 1 else: wildcards = wildcards | openflow.OFPFW_NW_TOS m.wildcards = wildcards # print m.show() return m
class Host(Node): def __init__(self, name, mymac, myip): Node.__init__(self, name, 1) self.mymac = MacAddress(mymac) self.myip = IpAddress(myip) self.arp_table = {} def start(self, model_checker): Node.start(self, model_checker) def build_ethernet_packet(self, name, dst, payload, type): eth = ethernet.ethernet(name) eth.packet_id = self.genPacketID() eth.set_payload(payload) if type != 0: eth.type = type eth.src = self.mymac.copy() eth.dst = dst.copy() return eth def build_ipv4_packet(self, protocol, dst, payload): ippkt = ipv4.ipv4() ippkt.protocol = protocol ippkt.srcip = self.myip.copy() ippkt.dstip = dst.copy() ippkt.set_payload(payload) return ippkt def build_arp_packet(self, opcode, hwdst, protodst): arppkt = arp.arp() arppkt.protosrc = self.myip.copy() arppkt.protodst = protodst.copy() arppkt.hwsrc = self.mymac.copy() arppkt.opcode = opcode return arppkt def build_tcp_packet(self, srcport, dstport, flags, flow_id, seq, ack): pkt = tcp.tcp() pkt.srcport = srcport pkt.dstport = dstport pkt.flags = flags pkt.seq = seq pkt.ack = ack pkt.flow_id = flow_id return pkt def manage_arp_packet(self, arp_pkt): """ RFC 826 without support for different protocol types """ # import pdb; pdb.set_trace() if arp_pkt.prototype != arp.arp.PROTO_TYPE_IP: return merge_flag = False if self.arp_table.has_key(arp_pkt.hwsrc): self.log.debug("Adding %s to ARP table" % str( (arp_pkt.hwsrc, arp_pkt.protosrc))) self.arp_table[arp_pkt.hwsrc] = arp_pkt.protosrc merge_flag = True if self.myip == arp_pkt.protodst: if not merge_flag: self.log.debug("Adding %s to ARP table" % str( (arp_pkt.hwsrc, arp_pkt.protosrc))) self.arp_table[arp_pkt.hwsrc] = arp_pkt.protosrc if arp_pkt.opcode == arp.arp.REQUEST: reply = self.build_arp_packet(arp.arp.REPLY, arp_pkt.hwsrc, arp_pkt.protosrc) reply = self.build_ethernet_packet("arp_reply", arp_pkt.hwsrc, reply, ARP_TYPE) self.sendPacket(reply, 0) def arp_query(self, ip): name = "arp_query" + str(ip) packet = self.build_arp_packet(arp.arp.REQUEST, MacAddress("0:0:0:0:0:0"), ip) packet = self.build_ethernet_packet(name, ethernet.ETHER_BROADCAST, packet, ARP_TYPE) self.sendPacket(packet, 0) return True def ip2mac(self, ip): destmac = None for mac in self.arp_table: if self.arp_table[mac] == ip: destmac = mac break if destmac != None: return destmac else: # We need to do an ARP query self.log.info("Issuing ARP Request for %s" % ip) self.arp_query(ip) return None def process_packet(self): raise NotImplementedError @abc.abstractmethod def dump_equivalent_state(self): filtered_dict = Node.dump_equivalent_state(self) filtered_dict["arp_table"] = utils.copy_state(self.arp_table) return filtered_dict
def processActions(self, packet, actions, inport): """Process a set of actions on the packet""" for action in actions: if action[0] == openflow.OFPAT_OUTPUT: port = action[1][1] if port < openflow.OFPP_MAX: peer = self.getPeer(port) if peer == None: continue # Skip disconnected port self.enqueuePacketToNode(peer, packet.copy(), self.getPeerPort(port)) self.state.testPoint("switch_sent_packet_on_port", switch=self, packet=packet, port=port) elif port == openflow.OFPP_FLOOD: self.state.testPoint("switch_flood_packet_start", switch=self, packet=packet) for port in self.ports: if port == inport: continue # Skip the inport peer = self.getPeer(port) if peer == None: continue # Skip disconnected port self.enqueuePacketToNode(peer, packet.copy(), self.getPeerPort(port)) self.state.testPoint("switch_sent_packet_on_port", switch=self, packet=packet, port=port) elif port == openflow.OFPP_CONTROLLER: self.sendQueryToController(packet, inport, openflow.OFPR_ACTION, action[1][0]) elif port == openflow.OFPP_IN_PORT: peer = self.getPeer(inport) if peer == None: continue self.enqueuePacketToNode(peer, packet.copy(), self.getPeerPort(inport)) self.state.testPoint("switch_sent_packet_on_port", switch=self, packet=packet, port=inport) else: utils.crash("Unknown port action: 0x%x" % port) elif action[ 0] == openflow.OFPAT_SET_DL_SRC: # Set Ethernet source address packet.src = MacAddress(action[1]) elif action[ 0] == openflow.OFPAT_SET_NW_SRC: # Set IPv4 source address packet.next.srcip = IpAddress( action[1]) # We assume the next is an ipv4 elif action[ 0] == openflow.OFPAT_SET_DL_DST: # Set Ethernet destination address packet.dst = MacAddress(action[1]) elif action[ 0] == openflow.OFPAT_SET_NW_DST: # Set IPv4 source address packet.next.dstip = IpAddress( action[1]) # We assume the next is an ipv4 else: utils.crash("Action not implemented: %x" % action[0])