[Xorp-hackers] Constructing packets

Victor Faion vfaion at gmail.com
Mon Feb 23 15:39:52 PST 2009


On Fri, Feb 20, 2009 at 19:51, Pavlin Radoslavov
<pavlin at icsi.berkeley.edu> wrote:
> 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
>

Thank you for the help, the embed_*() and extract_*() functions are
working. I use embed_8() on each character of the string. I don't
understand when (or if) I need to use the alignment functions in
AlignData. When I receive the packet now I just use the extract_*()
functions and everything seems to be aligned.

A sort of related question, I was trying to put a timestamp in a
packet using TimeVal::sec(). To test the time functions I just did
this:

TimeVal now;
TimerList::system_gettimeofday(&now);
XLOG_INFO("Time is %s", now.pretty_print().c_str());

But when I run this I get something like this:

Time is Thu Apr  6 08:23:07 1972

even though the system clock is set right and date gives the right
time. Am I using these functions in the wrong way?

Cheers,
Victor



More information about the Xorp-hackers mailing list