def isValidIpPacket(self,event):
    # ipv4_packet = event.parsed.find("ipv4")
    ipv4_packet = event.parsed.find("ipv4")
    # Do more processing of the IPv4 packet
    src_ip = ipv4_packet.srcip
    dst_ip = ipv4_packet.dstip
    if(ipv4_packet.csum!=ipv4_packet.checksum()):
  	  print "Ip packet checksum not macthing"
  	  return False
    if(ipv4_packet.ttl<=1):
      if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'):
        print "My Packet accept at ",self.IPAddr
        print ipv4_packet
        if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL):
          self.handle_icmp(event)
        return False  
      print "TTL Invalid"
      icmp_rep = icmp()
      icmp_rep.type = 11 # TYPE_TIME_EXCEED
      #icmp_rep.code=0
      icmp_rep.next=unreach()

      # icmp_rep.next.seq=packet.payload.next.next.seq
      # icmp_rep.next.id=packet.payload.next.next.id
      # icmp_rep.next.raw=packet.payload.next.next.raw

      # Show the client that it's actually the me
      rep=ipv4()
      rep.srcip=self.IPAddr
      rep.dstip=ipv4_packet.srcip
      rep.next=icmp_rep
      rep.protocol=ipv4_packet.ICMP_PROTOCOL
      eth = ethernet()
      eth.dst = event.parsed.src
      eth.src = self.EthAddr
      eth.set_payload(rep)
      eth.type = ethernet.IP_TYPE
      msg = of.ofp_packet_out()
      msg.data = eth.pack()
      msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
      msg.in_port = event.port
      self.connection.send(msg)
      return False		
    if(ipv4_packet.iplen<20):
  	  print "Length Invalid"
  	  return False	
    # len > min_len
    return True
  def handle_ipPacket(self,event): # handle broad cast ip also 
    print "IP packet Received at R"+str(event.dpid)
    packet=event.parsed
    src_mac = packet.src
    dst_mac = packet.dst

    if dst_mac!=self.EthAddr and dst_mac!=EthAddr('ff:ff:ff:ff:ff:ff'):
      return
    
    if(not self.isValidIpPacket(event)):
      return

    ipv4_packet = event.parsed.find("ipv4")
    # Do more processing of the IPv4 packet
    src_ip = ipv4_packet.srcip
    dst_ip = ipv4_packet.dstip

    if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'):
      print "My Packet accept at ",self.IPAddr
      print ipv4_packet
      if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL):
      	self.handle_icmp(event)
    else:   
      nxt=self.FindNextHopInterface(dst_ip.toStr())
      if(nxt[0]==-1):   # need to send an icmp packet 
        # print "No Route to Host"
        # Create ARP reply
        icmp_rep = icmp()
        icmp_rep.type = 3
        icmp_rep.code= nxt[2]
        icmp_rep.next=unreach()

        # icmp_rep.next.seq=packet.payload.next.next.seq
        # icmp_rep.next.id=packet.payload.next.next.id
        # icmp_rep.next.raw=packet.payload.next.next.raw

        # Show the client that it's actually the me
        rep=ipv4()
        rep.srcip=self.IPAddr
        rep.dstip=src_ip
        rep.next=icmp_rep
        rep.protocol=packet.payload.ICMP_PROTOCOL
        eth = ethernet()
        eth.dst = packet.src
        eth.src = self.EthAddr
        eth.set_payload(rep)
        eth.type = ethernet.IP_TYPE
        msg = of.ofp_packet_out()
        msg.data = eth.pack()
        msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
        msg.in_port = event.port
        self.connection.send(msg)
        print "icmp reply DONE"

      else:
        NextHopIP=nxt[0]
        Interface=nxt[1][-1]

        # payload=packet.payload.pa/yload # payload of IP packet
        # create a empty IP packet

        # ipv4_packet_out=ipv4_packet
        ipv4_packet.ttl=ipv4_packet.ttl-1
        # Create the Ethernet packet

        eth = ethernet()
        eth.type = ethernet.IP_TYPE
        if IPAddr(NextHopIP) in self.arp_table: 
          eth.dst = self.arp_table[IPAddr(NextHopIP)]
          eth.src = self.EthAddr
          eth.set_payload(ipv4_packet)

          # msg is the "packet out" message. Now giving this packet special properties
          msg = of.ofp_packet_out()
          msg.data = eth.pack()
          msg.actions.append(of.ofp_action_output(port = int(Interface)))
          msg.in_port = event.port
          self.connection.send(msg)
        else:
          arp_rep = arp()
          arp_rep.opcode = arp.REQUEST

          # Show the client that it's actually the me
          arp_rep.hwsrc = self.EthAddr
          arp_rep.hwdst = EthAddr('ff:ff:ff:ff:ff:ff')
          #arp_rep.hwdst = 'ff:ff:ff:ff:ff:ff'
          arp_rep.protosrc = self.IPAddr
          arp_rep.protodst = IPAddr(NextHopIP)

          # Create the Ethernet packet
          eth1 = ethernet()
          eth1.type = ethernet.ARP_TYPE
          eth1.dst = EthAddr('ff:ff:ff:ff:ff:ff')
          eth1.src = self.EthAddr
          eth1.set_payload(arp_rep)

          # Send the ARP reply to client
          # msg is the "packet out" message. Now giving this packet special properties
          msg = of.ofp_packet_out()
          msg.data = eth1.pack()
          msg.actions.append(of.ofp_action_output(port = int(Interface)))
          msg.in_port = event.port
          self.connection.send(msg)
          eth.src = self.EthAddr
          eth.set_payload(ipv4_packet_out)
          self.que.append((eth,int(Interface),event.port))
  def handle_ipPacket(self,event): # handle broad cast ip also 
    # print "IP packet Received at R"+str(event.dpid)

    packet=event.parsed
    if(packet is None):
    	print "error"
    	print event
    src_mac = packet.src
    dst_mac = packet.dst

    ipv4_packet = event.parsed.next
    if(ipv4_packet is None):
      print "error"
      print event
    # Do more processing of the IPv4 packet
    src_ip = ipv4_packet.srcip
    dst_ip = ipv4_packet.dstip
    global _hello_tos, _lsu_tos
    if ipv4_packet.tos == _hello_tos:
      print "HELLO at R"+str(event.dpid)+" from "+src_ip.toStr()
      self.neighbours[event.port]=src_ip
      self.times[event.port]=time.time()
      self.G.add_edge(self.IPAddr,src_ip)
      self.send_lsu()
      return

    if ipv4_packet.tos == _lsu_tos:
      if src_ip==self.IPAddr:
        return
      print "LSU at R"+str(event.dpid)+" from "+src_ip.toStr()
      self.times2[src_ip]=time.time()
      pl=ipv4_packet.next
      lst=pl.split(':')[:-1]
      if src_ip in self.seqnum.keys() and self.seqnum[src_ip]>=int(pl[0]):
      	return
      self.seqnum[src_ip]=int(pl[0])
      ed=[i for i in self.G.edges() if i[0]==src_ip]
      try:
        self.G.remove_edges_from(ed)
      except:
        pass
      for i in lst[1:]:
      	self.G.add_edge(src_ip,IPAddr(i))
      eth = ethernet()
      eth.src = self.EthAddr
      eth.set_payload(ipv4_packet)
      eth.type = ethernet.IP_TYPE
      msg = of.ofp_packet_out()
      msg.data = eth.pack()
      msg.actions.append(of.ofp_action_output(port = of.OFPP_ALL))
      self.connection.send(msg)
      return

    if dst_mac!=self.EthAddr and dst_mac!=EthAddr('ff:ff:ff:ff:ff:ff'):
      return
    
    if(not self.isValidIpPacket(event)):
      return

    if(dst_ip==self.IPAddr or dst_ip.toStr()=='255.255.255.255'):
      if(packet.payload.protocol==packet.payload.ICMP_PROTOCOL):
      	self.handle_icmp(event)
    else:   
      nxt=self.FindNextHopInterface(dst_ip.toStr())
      if(nxt[0]==-1):   # need to send an icmp packet 
        # print "No Route to Host"
        # Create ARP reply
        icmp_rep = icmp()
        icmp_rep.type = 3
        icmp_rep.code= nxt[2]
        icmp_rep.next=unreach()

        # icmp_rep.next.seq=packet.payload.next.next.seq
        # icmp_rep.next.id=packet.payload.next.next.id
        # icmp_rep.next.raw=packet.payload.next.next.raw

        # Show the client that it's actually the me
        rep=ipv4()
        rep.srcip=self.IPAddr
        rep.dstip=src_ip
        rep.next=icmp_rep
        rep.protocol=packet.payload.ICMP_PROTOCOL
        eth = ethernet()
        eth.dst = packet.src
        eth.src = self.EthAddr
        eth.set_payload(rep)
        eth.type = ethernet.IP_TYPE
        msg = of.ofp_packet_out()
        msg.data = eth.pack()
        msg.actions.append(of.ofp_action_output(port = of.OFPP_IN_PORT))
        msg.in_port = event.port
        self.connection.send(msg)
        print "icmp reply DONE"

      else:
        NextHopIP=nxt[0]
        Interface=nxt[1][-1]

        payload=packet.payload.payload # payload of IP packet
        # create a empty IP packet

        ipv4_packet_out=ipv4_packet
        ipv4_packet_out.ttl=ipv4_packet_out.ttl-1
        # Create the Ethernet packet

        eth = ethernet()
        eth.type = ethernet.IP_TYPE
        if IPAddr(NextHopIP) in self.arp_table: 
          eth.dst = self.arp_table[IPAddr(NextHopIP)]
          eth.src = self.EthAddr
          eth.set_payload(ipv4_packet_out)

          # msg is the "packet out" message. Now giving this packet special properties
          msg = of.ofp_packet_out()
          msg.data = eth.pack()
          msg.actions.append(of.ofp_action_output(port = int(Interface)))
          msg.in_port = event.port
          self.connection.send(msg)
        else:
          arp_rep = arp()
          arp_rep.opcode = arp.REQUEST

          # Show the client that it's actually the me
          arp_rep.hwsrc = self.EthAddr
          arp_rep.hwdst = EthAddr('ff:ff:ff:ff:ff:ff')
          #arp_rep.hwdst = 'ff:ff:ff:ff:ff:ff'
          arp_rep.protosrc = self.IPAddr
          arp_rep.protodst = IPAddr(NextHopIP)

          # Create the Ethernet packet
          eth1 = ethernet()
          eth1.type = ethernet.ARP_TYPE
          eth1.dst = EthAddr('ff:ff:ff:ff:ff:ff')
          eth1.src = self.EthAddr
          eth1.set_payload(arp_rep)

          # Send the ARP reply to client
          # msg is the "packet out" message. Now giving this packet special properties
          msg = of.ofp_packet_out()
          msg.data = eth1.pack()
          msg.actions.append(of.ofp_action_output(port = int(Interface)))
          msg.in_port = event.port
          self.connection.send(msg)
          eth.src = self.EthAddr
          eth.set_payload(ipv4_packet_out)
          self.que.append((eth,int(Interface),event.port))