def get_rddata(self, l, type, dlen, beg_index): if beg_index + dlen > len(l): raise Trunc('(dns) truncated rdata') # A if type == 1: if dlen != 4: raise Exception('(dns) invalid a data size',system='packet') return IPAddr(l[beg_index : beg_index + 4]) # AAAA elif type == 28: if dlen != 16: raise Exception('(dns) invalid a data size',system='packet') return IPAddr6.from_raw(l[beg_index : beg_index + dlen]) # NS elif type == 2: return self.read_dns_name_from_index(l, beg_index)[1] # PTR elif type == 12: return self.read_dns_name_from_index(l, beg_index)[1] # CNAME elif type == 5: return self.read_dns_name_from_index(l, beg_index)[1] # MX elif type == 15: #TODO: Save priority (don't just jump past it) return self.read_dns_name_from_index(l, beg_index + 2)[1] else: return l[beg_index : beg_index + dlen]
def _unpack_new(cls, raw, offset, t, length, prev): o = cls() o.prefix_length,flags,o.valid_lifetime,o.preferred_lifetime = \ struct.unpack_from('!BBII', raw, offset) offset += 1 + 1 + 4 + 4 offset += 4 # Reserved o.prefix = IPAddr6(raw=raw[offset:offset + 16]) offset += 16 o.on_link = (flags & cls.ON_LINK_FLAG) != 0 o.is_autonomous = (flags & cls.AUTONOMOUS_FLAG) != 0 o.prev = prev return offset, o
def unpack_new(cls, raw, offset=0, buf_len=None, prev=None): o = cls() _offset = offset if buf_len is None: buf_len = len(raw) try: offset += 4 # Skip reserved o.target = IPAddr6(raw=raw[offset:offset + 16]) offset += 16 offset, o.options = _parse_ndp_options(raw, prev, offset, buf_len) o.parsed = True except TruncatedException: pass o.raw = raw[_offset:offset] o.prev = prev return offset, o
def unpack_new(cls, raw, offset=0, buf_len=None, prev=None): o = cls() _offset = offset if buf_len is None: buf_len = len(raw) try: flags = raw[offset] o.is_router = (flags & cls.ROUTER_FLAG) != 0 o.is_solicited = (flags & cls.SOLICITED_FLAG) != 0 o.is_override = (flags & cls.OVERRIDE_FLAG) != 0 offset += 4 # Skip reserved o.target = IPAddr6(raw=raw[offset:offset + 16]) offset += 16 offset, o.options = _parse_ndp_options(raw, prev, offset, buf_len) o.parsed = True except TruncatedException: pass o.raw = raw[_offset:offset] o.prev = prev return offset, o
class dns(packet_base): "DNS Packet struct" MDNS_ADDRESS = IPAddr('224.0.0.251') MDNS6_ADDRESS = IPAddr6('ff02::fb') MDNS_ETH = EthAddr('01:00:5E:00:00:fb') MDNS6_ETH = EthAddr('33:33:00:00:00:fb') SERVER_PORT = 53 MDNS_PORT = 5353 MIN_LEN = 12 def __init__(self, raw=None, prev=None, **kw): packet_base.__init__(self) self.prev = prev self.questions = [] self.answers = [] self.authorities = [] self.additional = [] self.id = 0 self.qr = False # Is Query self.opcode = 0 self.aa = False # Authoritative Answer self.tc = False # Truncated self.rd = False # Recursion Desired self.ra = False # Recursion Available self.z = False self.ad = False self.cd = False self.rcode = 0 # TODO: everything else here if raw is not None: self.parse(raw) self._init(kw) def _exc(self, e, part=None): """ Turn exception into log message """ msg = "(dns)" if part is not None: msg += " " + part msg += ": " msg += str(e) if isinstance(e, Trunc): self.msg(msg) else: self.err(msg) def hdr(self, payload): bits0 = 0 if self.qr: bits0 |= 0x80 bits0 |= (self.opcode & 0x7) << 4 if self.rd: bits0 |= 1 if self.tc: bits0 |= 2 if self.aa: bits0 |= 4 bits1 = 0 if self.ra: bits1 |= 0x80 if self.z: bits1 |= 0x40 if self.ad: bits1 |= 0x20 if self.cd: bits1 |= 0x10 bits1 |= (self.rcode & 0xf) s = struct.pack("!HBBHHHH", self.id, bits0, bits1, len(self.questions), len(self.answers), len(self.authorities), len(self.additional)) def makeName(labels, term): o = '' #TODO: unicode for l in labels.split('.'): o += chr(len(l)) o += l if term: o += '\x00' return o name_map = {} def putName(s, name): pre = '' post = name while True: at = s.find(makeName(post, True)) if at == -1: if post in name_map: at = name_map[post] if at == -1: post = post.split('.', 1) if pre: pre += '.' pre += post[0] if len(post) == 1: if len(pre) == 0: s += '\x00' else: name_map[name] = len(s) s += makeName(pre, True) break post = post[1] else: if len(pre) > 0: name_map[name] = len(s) s += makeName(pre, False) s += struct.pack("!H", at | 0xc000) break return s def putData(s, r): if r.qtype in (2, 12, 5, 15): # NS, PTR, CNAME, MX return putName(s, r.rddata) elif r.qtype == 1: # A assert isinstance(r.rddata, IPAddr) return s + r.rddata.raw elif r.qtype == 28: # AAAA assert isinstance(r.rddata, IPAddr6) return s + r.rddata.raw else: return s + r.rddata for r in self.questions: s = putName(s, r.name) s += struct.pack("!HH", r.qtype, r.qclass) rest = self.answers + self.authorities + self.additional for r in rest: s = putName(s, r.name) s += struct.pack("!HHIH", r.qtype, r.qclass, r.ttl, 0) fixup = len(s) - 2 s = putData(s, r) fixlen = len(s) - fixup - 2 s = s[:fixup] + struct.pack('!H', fixlen) + s[fixup + 2:] return s def parse(self, raw): assert isinstance(raw, bytes) self.raw = raw dlen = len(raw) if dlen < dns.MIN_LEN: self.msg('(dns) packet data too short to ' + 'parse header: data len %u' % (dlen, )) return None bits0 = 0 bits1 = 0 total_questions = 0 total_answers = 0 total_auth_rr = 0 total_add_rr = 0 (self.id, bits0,bits1, total_questions, total_answers, total_auth_rr, total_add_rr)\ = struct.unpack('!HBBHHHH', raw[:12]) self.qr = True if (bits0 & 0x80) else False self.opcode = (bits0 >> 4) & (0x07) self.aa = True if (bits0 & (0x04)) else False self.tc = True if (bits0 & (0x02)) else False self.rd = True if (bits0 & (0x01)) else False self.ra = True if (bits1 & 0x80) else False self.z = True if (bits1 & 0x40) else False self.ad = True if (bits1 & 0x20) else False self.cd = True if (bits1 & 0x10) else False self.rcode = bits1 & 0x0f query_head = 12 # questions for i in range(0, total_questions): try: query_head = self.next_question(raw, query_head) except Exception as e: self._exc(e, 'parsing questions') return None # answers for i in range(0, total_answers): try: query_head = self.next_rr(raw, query_head, self.answers) except Exception as e: self._exc(e, 'parsing answers') return None # authoritative name servers for i in range(0, total_auth_rr): try: query_head = self.next_rr(raw, query_head, self.authorities) except Exception as e: self._exc(e, 'parsing authoritative name servers') return None # additional resource records for i in range(0, total_add_rr): try: query_head = self.next_rr(raw, query_head, self.additional) except Exception as e: self._exc(e, 'parsing additional resource records') return None self.parsed = True def _to_str(self): flags = "|" if self.qr != 0: flags += "QR " if self.tc != 0: flags += "TR " if self.rd != 0: flags += "RD " if self.ra != 0: flags += "RA " if self.z != 0: flags += "Z " flags += "|" s = "(id:%x fl:%s op:%d nq:%d na:%d nath:%d nadd:%d)" % ( self.id, flags, self.opcode, len(self.questions), len( self.answers), len(self.authorities), len(self.additional)) if len(self.questions) > 0: for q in self.questions: s += "(q? " + str(q) + ")" if len(self.answers) > 0: for a in self.answers: s += "(answ: " + str(a) + ")" if len(self.authorities) > 0: for a in self.authorities: s += "(auth: " + str(a) + ")" if len(self.additional) > 0: for a in self.additional: s += "(add: " + str(a) + ")" return s # Utility methods for parsing. Generally these would be pulled out # into a separate class. However, because the lengths are not known # until the fields have been parsed, it is more convenient to keep # them in the DNS class @classmethod def _read_dns_name_from_index(cls, l, index, retlist): try: while True: chunk_size = ord(l[index]) # check whether we have an internal pointer if (chunk_size & 0xc0) == 0xc0: # pull out offset from last 14 bits offset = ((ord(l[index]) & 0x3) << 8) | ord(l[index + 1]) cls._read_dns_name_from_index(l, offset, retlist) index += 1 break if chunk_size == 0: break index += 1 retlist.append(l[index:index + chunk_size]) index += chunk_size return index except IndexError: raise Trunc("incomplete name") @classmethod def read_dns_name_from_index(cls, l, index): retlist = [] next = cls._read_dns_name_from_index(l, index, retlist) return (next + 1, b".".join(retlist)) def next_rr(self, l, index, rr_list): array_len = len(l) # verify whether name is offset within packet if index > array_len: raise Trunc("next_rr: name truncated") index, name = self.read_dns_name_from_index(l, index) if index + 10 > array_len: raise Trunc("next_rr: truncated") (qtype, qclass, ttl, rdlen) = struct.unpack('!HHIH', l[index:index + 10]) if index + 10 + rdlen > array_len: raise Trunc("next_rr: data truncated") rddata = self.get_rddata(l, qtype, rdlen, index + 10) rr_list.append(dns.rr(name, qtype, qclass, ttl, rdlen, rddata)) return index + 10 + rdlen def get_rddata(self, l, type, dlen, beg_index): if beg_index + dlen > len(l): raise Trunc('(dns) truncated rdata') # A if type == 1: if dlen != 4: raise Exception('(dns) invalid a data size', system='packet') return IPAddr(l[beg_index:beg_index + 4]) # AAAA elif type == 28: if dlen != 16: raise Exception('(dns) invalid a data size', system='packet') return IPAddr6.from_raw(l[beg_index:beg_index + dlen]) # NS elif type == 2: return self.read_dns_name_from_index(l, beg_index)[1] # PTR elif type == 12: return self.read_dns_name_from_index(l, beg_index)[1] # CNAME elif type == 5: return self.read_dns_name_from_index(l, beg_index)[1] # MX elif type == 15: #TODO: Save priority (don't just jump past it) return self.read_dns_name_from_index(l, beg_index + 2)[1] else: return l[beg_index:beg_index + dlen] def next_question(self, l, index): array_len = len(l) index, name = self.read_dns_name_from_index(l, index) if index + 4 > array_len: raise Trunc("next_question: truncated") (qtype, qclass) = struct.unpack('!HH', l[index:index + 4]) self.questions.append(dns.question(name, qtype, qclass)) return index + 4 # Utility classes for questions and RRs class question(object): def __init__(self, name, qtype, qclass): self.name = name self.qtype = qtype self.qclass = qclass def __str__(self): s = self.name if self.qtype in rrtype_to_str: s += " " + rrtype_to_str[self.qtype] else: s += " #" + str(self.qtype) if self.qclass in rrclass_to_str: s += " " + rrclass_to_str[self.qclass] else: s += " #" + str(self.qclass) return s class rr(object): A_TYPE = 1 NS_TYPE = 2 MD_TYPE = 3 MF_TYPE = 4 CNAME_TYPE = 5 SOA_TYPE = 6 MB_TYPE = 7 MG_TYPE = 8 MR_TYPE = 9 NULL_TYPE = 10 WKS_TYPE = 11 PTR_TYPE = 12 HINFO_TYPE = 13 MINFO_TYPE = 14 MX_TYPE = 15 TXT_TYPE = 16 AAAA_TYPE = 28 def __init__(self, _name, _qtype, _qclass, _ttl, _rdlen, _rddata): self.name = _name self.qtype = _qtype self.qclass = _qclass self.ttl = _ttl self.rdlen = _rdlen self.rddata = _rddata def __str__(self): s = self.name if self.qtype in rrtype_to_str: s += " " + rrtype_to_str[self.qtype] else: s += " #" + str(self.qtype) if self.qclass in rrclass_to_str: s += " " + rrclass_to_str[self.qclass] else: s += " #" + str(self.qclass) s += " ttl:" + str(self.ttl) s += " rdlen:" + str(self.rdlen) s += " datalen:" + str(len(self.rddata)) if len(self.rddata) == 4: #FIXME: can be smarter about whether this is an IP s += " data:" + str(IPAddr(self.rddata)) return s
class dns(packet_base): "DNS Packet struct" MDNS_ADDRESS = IPAddr('224.0.0.251') MDNS6_ADDRESS = IPAddr6('ff02::fb') MDNS_ETH = EthAddr('01:00:5E:00:00:fb') MDNS6_ETH = EthAddr('33:33:00:00:00:fb') SERVER_PORT = 53 MDNS_PORT = 5353 MIN_LEN = 12 def __init__(self, raw=None, prev=None, **kw): packet_base.__init__(self) self.prev = prev self.questions = [] self.answers = [] self.authorities = [] self.additional = [] self.id = 0 self.qr = False # Is Query self.opcode = 0 self.aa = False # Authoritative Answer self.tc = False # Truncated self.rd = False # Recursion Desired self.ra = False # Recursion Available self.z = False self.ad = False self.cd = False self.rcode = 0 # TODO: everything else here if raw is not None: self.parse(raw) self._init(kw) def _exc(self, e, part=None): """ Turn exception into log message """ msg = "(dns)" if part is not None: msg += " " + part msg += ": " msg += str(e) if isinstance(e, Trunc): self.msg(msg) else: self.err(msg) def hdr(self, payload): bits0 = 0 if self.qr: bits0 |= 0x80 bits0 |= (self.opcode & 0x7) << 4 if self.rd: bits0 |= 1 if self.tc: bits0 |= 2 if self.aa: bits0 |= 4 bits1 = 0 if self.ra: bits1 |= 0x80 if self.z: bits1 |= 0x40 if self.ad: bits1 |= 0x20 if self.cd: bits1 |= 0x10 bits1 |= (self.rcode & 0xf) s = struct.pack("!HBBHHHH", self.id, bits0, bits1, len(self.questions), len(self.answers), len(self.authorities), len(self.additional)) def makeName(labels, term): o = '' #TODO: unicode for l in labels.split('.'): o += chr(len(l)) o += l if term: o += '\x00' return o name_map = {} def putName(s, name): pre = '' post = name while True: at = s.find(makeName(post, True)) if at == -1: if post in name_map: at = name_map[post] if at == -1: post = post.split('.', 1) if pre: pre += '.' pre += post[0] if len(post) == 1: if len(pre) == 0: s += '\x00' else: name_map[name] = len(s) s += makeName(pre, True) break post = post[1] else: if len(pre) > 0: name_map[name] = len(s) s += makeName(pre, False) s += struct.pack("!H", at | 0xc000) break return s def putData(s, r): if r.qtype in (2, 12, 5, 15): return putName(s, r.rddata) elif r.qtype == 1: assert isinstance(r.rddata, IPAddr) return s + r.rddata.toRaw() else: return s + r.rddata for r in self.questions: s = putName(s, r.name) s += struct.pack("!HH", r.qtype, r.qclass) rest = self.answers + self.authorities + self.additional for r in rest: s = putName(s, r.name) s += struct.pack("!HHIH", r.qtype, r.qclass, r.ttl, 0) fixup = len(s) - 2 s = putData(s, r) fixlen = len(s) - fixup - 2 s = s[:fixup] + struct.pack('!H', fixlen) + s[fixup + 2:] return s def parse(self, raw): assert isinstance(raw, bytes) self.raw = raw dlen = len(raw) if dlen < dns.MIN_LEN: self.msg('(dns) packet data too short to ' + 'parse header: data len %u' % (dlen, )) return None bits0 = 0 bits1 = 0 total_questions = 0 total_answers = 0 total_auth_rr = 0 total_add_rr = 0 (self.id, bits0,bits1, total_questions, total_answers, total_auth_rr, total_add_rr)\ = struct.unpack('!HBBHHHH', raw[:12]) self.qr = True if (bits0 & 0x80) else False self.opcode = (bits0 >> 4) & (0x07) self.aa = True if (bits0 & (0x04)) else False self.tc = True if (bits0 & (0x02)) else False self.rd = True if (bits0 & (0x01)) else False self.ra = True if (bits1 & 0x80) else False self.z = True if (bits1 & 0x40) else False self.ad = True if (bits1 & 0x20) else False self.cd = True if (bits1 & 0x10) else False self.rcode = bits1 & 0x0f query_head = 12 # questions for i in range(0, total_questions): try: query_head = self.next_question(raw, query_head) except Exception, e: self._exc(e, 'parsing questions') return None # answers for i in range(0, total_answers): try: query_head = self.next_rr(raw, query_head, self.answers) except Exception, e: self._exc(e, 'parsing answers') return None
def parse(self, raw, offset=0): assert isinstance(raw, bytes) self.next = None # In case of unfinished parsing self.raw = raw if len(raw) < self.MIN_LEN: self.msg('warning IP packet data too short to parse header:' ' data len %u' % (len(raw), )) return (vtcfl, self.payload_length, nht, self.hop_limit) \ = struct.unpack('!IHBB', raw[offset:offset+8]) self.srcip = IPAddr6(raw[offset + 8:offset + 24], raw=True) self.dstip = IPAddr6(raw[offset + 24:offset + 40], raw=True) self.next_header_type = nht offset += 40 self.v = vtcfl >> 28 self.tc = (vtcfl >> 20) & 0xff self.flow = vtcfl & 0xfffff if self.v != 6: self.msg('ip parse) warning IP version %u not IPv6' % self.v) return length = self.payload_length if length > len(raw): length = len(raw) # Clamp to what we've got self.msg('(ipv6) warning IP packet data incomplete (%s of %s)' % (len(raw), self.payload_length)) while nht != ipv6.NO_NEXT_HEADER: c = _extension_headers.get(nht) if c: if length < 8: self.msg('(ipv6) warning, packet data incomplete') return try: offset, o = c.unpack_new(raw, offset, max_length=length) length -= len(o) except TruncatedException: self.msg('(ipv6) warning, packet data truncated') return self.extension_headers.append(o) nht = o.next_header_type else: break self.parsed = True #TODO: This should be done a better way (and shared with IPv4?). if nht == self.UDP_PROTOCOL: self.next = udp(raw=raw[offset:offset + length], prev=self) elif nht == self.TCP_PROTOCOL: self.next = tcp(raw=raw[offset:offset + length], prev=self) elif nht == self.ICMP6_PROTOCOL: self.next = icmpv6(raw=raw[offset:offset + length], prev=self) # elif nht == self.IGMP_PROTOCOL: # self.next = igmp(raw=raw[offset:offset+length], prev=self) elif nht == self.NO_NEXT_HEADER: self.next = None else: self.next = raw[offset:offset + length] if isinstance(self.next, packet_base) and not self.next.parsed: self.next = raw[offset:offset + length]
def ip6(addr): if addr is None: return None return IPAddr6.from_raw(addr)
0x2f, 0x93, 0x0a, 0x00, 0x02, 0x0f, 0xc3, 0x58, 0x36, 0x10] payload_packet = b"".join(map(chr, ipv4_header)) ethernet_packet_b = b"".join(map(chr, ethernet_packet)) ''' ''' This is a Client. Can be an IoT Device and use CoAP communication. We just send an IP packet without actually knowing IPv6 with just a tag in the IP packet payload. ''' #Create an IP packet ipv6_packet = ipv6() ipv6_packet.srcip = IPAddr6("::0") #Random IP destination address ipv6_packet.dstip = IPAddr6("::7") ipv6_packet.next_header_type = 0xFD # Set a tag in IP payload. e.g color = red. Tag-Based Forwarding ipv6_packet.payload = "[color='red']" ether = ethernet() ether.type = 0x86DD # Because we don't know the destination mac address we set :00 as mac ether.dst = EthAddr(b"\x00\x00\x00\x00\x00\x00") ether.src = EthAddr(b"\x08\x00\x27\xc8\x18\xa5") ether.payload = ipv6_packet
def __init__(self, connection): self.connection = connection connection.addListeners(self) if (connection.eth_addr.toStr() == "00:00:00:00:00:01"): print "Preparing of rules" msg = nx.nx_flow_mod_table_id() connection.send(msg) #table 0 msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 1 msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::1"), IPAddr6("::1")) msg.actions.append(of.ofp_action_output(port=1)) msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) #table 1 msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::2"), IPAddr6("::2")) msg.actions.append(of.ofp_action_output(port=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 2 self.connection.send(msg) if (connection.eth_addr.toStr() == "00:00:00:00:00:02"): print "Preparing of rules" msg = nx.nx_flow_mod_table_id() connection.send(msg) #table 0 msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 1 msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::2"), IPAddr6("::2")) msg.actions.append(of.ofp_action_output(port=1)) msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) #table 1 msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::4"), IPAddr6("::4")) msg.actions.append(of.ofp_action_output(port=2)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 2 self.connection.send(msg)
def __init__(self, connection): self.connection = connection connection.addListeners(self) if (connection.eth_addr.toStr() == "00:00:00:00:00:01"): # Rules for switch s1 ! ''' Table id is a number for the the table of rules for each switch. Priority is for overlapping matches. Higher values are higher priority. in_port - If using a buffer_id, this is the associated input port. match - An ofp_match object. By default, this matches everything, so you should probably set some of its fields! ''' print "Preparing of rules" msg = nx.nx_flow_mod_table_id() connection.send(msg) #table 0 - Rules for IP :01 ''' Forward a packet to source if the port that is coming is the same as the input ''' msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 1 msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) ''' When a message comes to the Switch if has a rule for this IPv6 forward it to next port ''' msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::1"), IPAddr6("::1")) msg.actions.append(of.ofp_action_output(port=1)) msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) ''' If you have no rule for this IP check table 1 for IP :02 ''' msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) #table 1 - Rules for IP :02 msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::2"), IPAddr6("::2")) msg.actions.append(of.ofp_action_output(port=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 2 self.connection.send(msg) if (connection.eth_addr.toStr() == "00:00:00:00:00:02"): # Rules for switch s2 ! print "Preparing of rules" ''' The same Rules also for Switch 2 check the above comments.. ''' msg = nx.nx_flow_mod_table_id() connection.send(msg) #table 0 msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 1 msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::2"), IPAddr6("::2")) msg.actions.append(of.ofp_action_output(port=1)) msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 0 msg.priority = 500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.actions.append(nx.nx_action_resubmit.resubmit_table(table=1)) self.connection.send(msg) #table 1 msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1000 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.nx_ipv6_dst = (IPAddr6("::4"), IPAddr6("::4")) msg.actions.append(of.ofp_action_output(port=2)) self.connection.send(msg) msg = nx.nx_flow_mod() msg.table_id = 1 msg.priority = 1500 msg.match.of_eth_dst = "00:00:00:00:00:00" msg.match.of_eth_type = 0x86dd msg.match.of_in_port = 2 self.connection.send(msg)