Thanks. Let me try your code and let me also try using a different branch. But I think you are not getting this error because you are sending a packet as an argument to the set_payload method and hence the code "elif type(payload) == array.array:" never gets called because "if isinstance(payload, packet_base):" will always be true for such cases. (Please see below)
from packet_base.py =================== def set_payload(self, payload): '''Set the packet payload. Expects a string, array to packet of type packet_base''' if isinstance(payload, packet_base): self.next = payload payload.prev = self elif type(payload) == type(''): self.next = payload elif type(payload) == array.array: self.next = payload.tostring() else: self.msg('warning, payload must be string, array or type packet_base') --Saurabh ----- Original Message ----- From: Aaron Rosen <aro...@clemson.edu> To: Saurabh S Sabnis <ssabn...@gatech.edu> Cc: nox-dev <nox-dev@noxrepo.org>, Bernd Wittefeld <s9bew...@stud.uni-saarland.de> Sent: Thu, 26 Jan 2012 15:33:45 -0500 (EST) Subject: Re: [nox-dev] Creating and sending udp packet from controller through switch Here's an example of sending a UDP packet. If you want to send an ICMP packet just change l4=icmp() (and fill in the icmp fields) and the l3.protocol type to icmp. Aaron P.S: I'm using the latest nox destiny and I didn't need to change any internal nox code. def send_udp(mac, dstip, srcip, srcport, dstport, payload): l4 = udp() l4.srcport = srcport l4.dstport = dstport l4.len = udp.MIN_LEN + len(payload) l4.set_payload(payload) l4.arr = l4.tostring() l3 = ipv4() l3.iplen = ipv4.MIN_LEN + l4.len l3.protocol = ipv4.UDP_PROTOCOL l3.dstip = dstip l3.srcip = srcip l3.set_payload(l4) l2 = ethernet() l2.set_payload(l3) l2.dst = mac l2.src = octstr_to_array(CONTROLLER_MAC) l2.type = ethernet.IP_TYPE l4.csum = l4.checksum() return l2 then: send_openflow_packet(dpid, send_udp(mac, dstip, srcip, srcport, dstport, payload).tostring(), inport) On Thu, Jan 26, 2012 at 2:43 PM, Sabnis, Saurabh S <ssabn...@gatech.edu> wrote: > Hi, > > I have similar doubt. I was trying to send ICMP unreachable packets back to > host but when I tried to set the payload of unreach() packet to > "packet.next.arr[0:packet.next.hl * 4 + 8]", I got an error due to missing > 'import array' statement. After inserting it in the packet_base.py file I got > the following error. > > 00074|pyrt|ERR:unable to invoke a Python event handler: > Traceback (most recent call last): > File "./nox/lib/util.py", line 116, in f > event.total_len, buffer_id, packet) > File "./nox/coreapps/examples/printpacket.py", line 185, in > packet_in_callback > route_packet(self,dpid, inport, packet, packet.arr, bufid) > File "./nox/coreapps/examples/printpacket.py", line 173, in route_packet > learn_and_forward(self,dpid,inport,packet,buf,bufid) > File "./nox/coreapps/examples/printpacket.py", line 132, in learn_and_forward > send_dest_unreach(self,dpid,packet,inport) > File "./nox/coreapps/examples/printpacket.py", line 89, in send_dest_unreach > unreach_packet.set_payload(packet.next.arr[0:packet.next.hl * 4 + 8]) > File "./nox/lib/packet/packet_base.py", line 96, in set_payload > elif type(payload) == array.array: > AttributeError: type object 'array.array' has no attribute 'array' > > Then to work around, I did not set the payload of unreach() and created other > wrapper packets and sent them to the host using sed_openflow_packet method. > This method requires eth.tostring() method which calls hdr and checksum > methods of ipv4.py. But then it again gets stuck there by giving following > error: > > File "./nox/coreapps/examples/printpacket.py", line 185, in > packet_in_callback > route_packet(self,dpid, inport, packet, packet.arr, bufid) > File "./nox/coreapps/examples/printpacket.py", line 173, in route_packet > learn_and_forward(self,dpid,inport,packet,buf,bufid) > File "./nox/coreapps/examples/printpacket.py", line 132, in learn_and_forward > send_dest_unreach(self,dpid,packet,inport) > File "./nox/coreapps/examples/printpacket.py", line 119, in send_dest_unreach > self.send_openflow_packet(dpid, unreach_eth.tostring(), > inport,openflow.OFPP_NONE) > File "./nox/lib/packet/packet_base.py", line 117, in tostring > return ''.join((buf, self.next.tostring())) > File "./nox/lib/packet/packet_base.py", line 112, in tostring > buf = self.hdr() > File "./nox/lib/packet/ipv4.py", line 167, in hdr > self.csum = self.checksum() > File "./nox/lib/packet/ipv4.py", line 162, in checksum > self.dstip) > error: 'H' format requires 0 <= number <= 65535 > > I printed the values of the attributes used in these functions and found out > that the self.id attribute of ipv4 packet has value more than 65535. It is > generated using int(time.time()) function. So I changed the statement to > int(time.time()) % 65535 and went ahead. > > Now I am able to send my packet to the host and I can see it in Wireshark but > my host is not giving me destination unreachable error. There are several > problems here. Can someone please help me regarding this. My code is as > follows: > > def send_dest_unreach(self,dpid,packet,inport): > > unreach_packet = unreach() > unreach_packet.unused = 0 > unreach_packet.next_mtu = 0 > > # unreachable messages include the IP header and the first 8 bytes of > the > # packet that couldn't reach its destination > #print packet.next.arr[0:packet.next.hl * 4 + 8] > unreach_packet.set_payload(packet.next.arr[0:packet.next.hl * 4 + 8]) > #unreach_packet.arr = packet.next.arr[0:packet.next.hl * 4 + 8] > > unreach_icmp = icmp() > unreach_icmp.type = 3 # unreachable > unreach_icmp.code = 0 # network unreachable > unreach_icmp.set_payload(unreach_packet) > > # icmp (unlike ipv4) doesn't automatically calculate its checksum, so > we > # have to do it ourself > unreach_icmp.csum = packet_utils.checksum(unreach_icmp.tostring(), 0) > > unreach_ip = ipv4() > > # length of the header plus the length of the payload > unreach_ip.iplen = unreach_ip.hl * 4 + len(unreach_icmp.tostring()) > > unreach_ip.protocol = ipv4.ICMP_PROTOCOL > unreach_ip.srcip = packet.next.dstip # Hmm... ? > unreach_ip.dstip = packet.next.srcip > unreach_ip.set_payload(unreach_icmp) > print_packet(unreach_ip,"ID") > > unreach_eth = ethernet() > unreach_eth.src = packet.dst # I wonder what this should actually > be... ? > unreach_eth.dst = packet.src > unreach_eth.type = packet.type > unreach_eth.set_payload(unreach_ip) > > ----- Original Message ----- > From: Aaron Rosen <aro...@clemson.edu> > To: Bernd Wittefeld <s9bew...@stud.uni-saarland.de> > Cc: nox-dev <nox-dev@noxrepo.org> > Sent: Thu, 26 Jan 2012 14:03:38 -0500 (EST) > Subject: Re: [nox-dev] Creating and sending udp packet from controller > through switch > > Hi, > > You need to set the length field in the Ipv4 packet. > > ipv4_packet.iplen = ipv4.MIN_LEN + udp_packet.len() > > should do the trick. > > Aaron > > On Thu, Jan 26, 2012 at 1:42 PM, Bernd Wittefeld > <s9bew...@stud.uni-saarland.de> wrote: >> Hi, >> I have a python component and want to create an udp packet in the controller >> and send it out via "self.send_openflow_packet(dpid, packet.tostring(), >> outport)" >> >> First of all: a small bugfix is needed: >> nox/src/nox/lib/packet/packet_base.py needs an "import array". Without that, >> the set_payload function raises an exception as it does not find >> array.array. >> >> Now I create my packet the following way: >> >> from nox.lib.packet.udp import udp >> from nox.lib.packet.ipv4 import ipv4 >> from nox.lib.packet.ethernet import ethernet >> >> udp_packet = udp() >> udp_packet.srcport = 12345 >> udp_packet.dstport = 4711 >> rand = random.random() >> udp_packet.set_payload(str(rand)) >> udp_packet.csum = udp_packet.checksum() >> >> ipv4_packet = ipv4() >> ipv4_packet.set_payload(udp_packet) >> ipv4_packet.srcip = ipstr_to_int(CONTROLLER_IP) >> ipv4_packet.dstip = ipstr_to_int(CONTROLLER_IP) >> ipv4_packet.csum = ipv4_packet.checksum() >> >> eth_packet = ethernet() >> eth_packet.src = CONTROLLER_MAC >> eth_packet.dst = CONTROLLER_MAC >> eth_packet.set_payload(ipv4_packet) >> eth_packet.type = ethernet.IP_TYPE >> >> and send this then via self.send_openflow_packet >> >> The packet goes out the link and is forwarded (via a flow on another switch) >> back to the controller where I can see it in my packet_in handler. >> The only problem is: the packet only consists of the link layer (ethernet >> type) header and the ipv4 type header. The payload of the ipv4 packet (which >> should be my udp header and the payload) is completely missing. From the >> ipv4 class, the ipv4.next is None and I can also verify with wireshark that >> the packet that is transmitted from the controller to the switch encapsuled >> in an OpenFlow packet, consists only of the ethernet header and the ipv4 >> header. >> Am I missing something? Where is this going wrong? >> I tried to look at the send_openflow_packet function. It seems to somehow >> call self.ctxt.send_openflow_packet_port in nox/src/nox/lib/core.py which I >> could not find?! >> I am not into Swig and all that stuff, so I am stuck here :( >> >> Any help is greatly appreciated! >> >> >> Best regards >> >> Bernd >> >> _______________________________________________ >> nox-dev mailing list >> nox-dev@noxrepo.org >> http://noxrepo.org/mailman/listinfo/nox-dev > > > > -- > Aaron O. Rosen > Masters Student - Network Communication > 306B Fluor Daniel > _______________________________________________ > nox-dev mailing list > nox-dev@noxrepo.org > http://noxrepo.org/mailman/listinfo/nox-dev > -- Aaron O. Rosen Masters Student - Network Communication 306B Fluor Daniel _______________________________________________ nox-dev mailing list nox-dev@noxrepo.org http://noxrepo.org/mailman/listinfo/nox-dev