[Xorp-hackers] Constructing packets
Pavlin Radoslavov
pavlin at ICSI.Berkeley.EDU
Fri Feb 20 11:51:25 PST 2009
Victor Faion <vfaion at gmail.com> wrote:
> I was trying to construct a simple packet and send it over a socket. I
> defined the header like this:
>
> typedef struct bpsfhdr {
> uint8_t type;
> uint32_t src;
> } bpsfhdr;
>
> Then to construct it and send it I did this just as a test:
>
> vector<uint8_t> data;
> data.reserve(sizeof(bpsfhdr));
> bpsfhdr hdr;
> hdr.type = 42;
> hdr.src = ip.addr();
> memcpy(&data[0], &hdr, sizeof(bpsfhdr));
> socketCl.send_send(dst, sockid, data,
> callback(this, &Neighbour::send_cb));
You shouldn't be using method vector<>::reserve() because all it
does is helping avoiding re-allocation (e.g., if you call
vector<>::resize()).
E.g., if you print data.size() right resize(), you will get 0.
Instead, you should use data.resize(...) or even better just specify
the size when you declare the vector variable:
vector<uint8_t> data(sizeof(bpsfhdr));
> I didn't really know how to put the data inside the vector. For
> example if I use the copy_out() function of the IPv4 class I thought
> the IP address would overflow if I just had a uint8_t field in the
> struct. Is there a higher level way of adding data into the packets
You can use the above mechanism (write the data to a struct, and then
copying it to the buffer), but you have to be careful with the
host/network ordering of the values, and with the padding in the
structure.
Alternatively, you can use the embed_*() and extract_*() functions
in libproto/packet.hh which allow you to write directly to the
output buffer. By using this appropac you avoid the extra memory
copy, and you don't have the host/network ordering and padding
issues.
> passed into send_send, for example, adding a variable length string?
> Can I have for example a field of type string inside the struct? I
> think this is where I am going wrong, but I looked at a few examples
> in other XORP processes and it was done in a similar way.
You can't just use the C++ string and just copy it on the wire. You
must use C-style string (basically a variable length array with the
string value).
There are different ways to encode the string on the wire; one of
the simplest is to define a fixed max-length for the string itself
and reserve that space in your packet. Then have the string
zero-terminated as in C to avoid the extra encoding of the length
itself.
> To receive/umarshall the packet in socket4_user_0_1_recv_event I used
> the AlignData class:
>
> AlignData<struct bpsfhdr> aligned(pdata);
> const struct bpsfhdr* pkt = aligned.payload();
> uint8_t type = pkt->type;
> IPv4 src(pkt->src);
> XLOG_INFO("type = %u src = %s", type, src.str().c_str());
>
> But when I run this I get the following error:
>
> xorp_fea: asyncio.cc:450: void AsyncFileWriter::add_data(const
> std::vector<uint8_t, std::allocator<uint8_t> >&, const
> ref_ptr<XorpCallback4<void, AsyncFileOperator::Event, const uint8_t*,
> size_t, size_t> >&): Assertion `data.size() != 0' failed.
> [ 2009/02/19 17:15:58 ERROR xorp_rtrmgr:30765 RTRMGR +754
> module_manager.cc done_cb ] Command
> "/root/project/xorp1.6/install/fea/xorp_fea": terminated with signal
> 6; aborted with a core dump.
You get the above assert because the original data size was zero
(because of the usage of reserve()).
Regards,
Pavlin
More information about the Xorp-hackers
mailing list