Merge lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl
- hipl_retransmissions
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 6206 |
Proposed branch: | lp:~martin-lp/hipl/hipl_retransmissions |
Merge into: | lp:hipl |
Diff against target: |
650 lines (+249/-84) 9 files modified
hipd/hadb.c (+15/-6) hipd/init.c (+31/-6) hipd/input.c (+119/-5) hipd/input.h (+6/-0) hipd/maintenance.c (+39/-45) hipd/netdev.c (+8/-5) hipd/output.c (+13/-12) lib/core/state.h (+7/-4) modules/update/hipd/update.c (+11/-1) |
To merge this branch: | bzr merge lp:~martin-lp/hipl/hipl_retransmissions |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Diego Biurrun | Abstain | ||
Miika Komu | Approve | ||
Review via email: mp+87072@code.launchpad.net |
This proposal supersedes a proposal from 2011-12-20.
Commit message
Description of the change
Update:
Remarks on the code have been addressed in revisions 6224ff.
Previous description:
This branch fixes and improves the currently partially broken retransmissions in HIPL.
In short:
- buffer up to three retransmissions in simple round-robin style
-> this does not affect regular management packets during BEX but makes it possible to retransmit the locators of the second UPDATE packet
- we remove buffered retransmission based on incoming packets from the peer
-> hip_update_
-> for example an incoming R1 invalidates or acknowledges our buffered I1 retransmission
-> it's the same for UPDATE packets. incoming U2 invalidates buffered U1, and U3 invalidates U2 respectively
-> the rationale: if we do not get a response from the peer we can assume our or their packet was lost, so we retransmit. A received packet from the peer acts as acknowledgment and we remove the retransmissions. For this reason R2 and U3 packets do not get buffered for retransmission. Their retransmission is triggered by the peers retransmission of I2 or U2 respectively.
I have relatively thoroughly tested this and in the normal use case (no relay, opportunistic or what else we offer in special use cases) it works fine. Would be great if someone had a look at the other cases.
How to test these changes:
- decrease retransmission timeout define HIP_RETRANSMIT_WAIT in hipd.h (retransmission waiting time is still awfully long at the moment but out of scope of this branch to be changed)
- modify the packet loss defines in output.c (thanks Miika for the hint!)
-> if it does not compile cast the random() call to uint64_t
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
review needs-fixing
On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
> David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
>
> --- hipd/hadb.c 2011-11-17 11:15:47 +0000
> +++ hipd/hadb.c 2011-12-20 11:41:33 +0000
> @@ -693,17 +693,25 @@
> }
>
> - entry->
>
> /* Initialize module states */
You should remove an excess empty line here.
> --- hipd/input.c 2011-12-09 09:32:56 +0000
> +++ hipd/input.c 2011-12-20 11:41:33 +0000
> @@ -1877,3 +1873,117 @@
> +
> +/**
> + * Clear the given retransmission.
> + * i.e. set the remaining retransmissions to zero and zero the buffer.
> + *
> + * @param retrans The retransmission to be cleared.
> + */
> +void hip_clear_
> +{
> + if (!retrans) {
> + return;
> + }
> +
> + retrans->count = 0;
> + if (retrans->buf) {
> + memset(
sizeof(
> +/**
> + * Update our buffered retransmissions after receiving the given packet.
> + * This functions removes invalid retransmissions after a state change caused
> + * by a received packet. For example after successfully receiving and handling
> + * an I2 or R2 packet all our buffered packets are dropped.
> + *
> + * Call this function after successful handling of the incoming packet.
> + *
> + * @param packet_type The packet type of the control message (RFC 5201, 5.3.)
> + * @param ha_state The host association state (RFC 5201, 4.4.1.)
> + * @param ctx The packet context of the incoming transmission.
> + *
> + * @return always 0
> + */
Why always return 0?
> +int hip_update_
> + UNUSED const enum hip_state ha_state,
> + struct hip_packet_context *const ctx)
> +{
> + struct hip_msg_retrans *retrans;
> +
> + HIP_ASSERT(ctx);
> + HIP_ASSERT(
> +
> + /* When receiving an I1 there usually is no established state yet. */
> + if (!ctx->hadb_entry) {
> + return 0;
> + }
> +
> + for (unsigned int i = 0; i < HIP_RETRANSMIT_
> + retrans = &ctx->hadb_
> +
> + if (retrans->count == 0) {
> + continue;
> + }
> +
> + switch (hip_get_
> + case HIP_I1:
> + switch (hip_get_
> + case HIP_I1:
> + /* We only remove our sent I1s when we have got a greater HIT
> + * than the peer (ref. RFC 5201, 4.4.2). */
> + if (hip_hit_
> + hip_clear_
> + }
> + break;
> + }
> + break;
This nested switch statement for only one case looks pretty weird IMO.
> --- hipd/maintenance.c 2011-12-16 13:37:33 +0000
> +++ hipd/maintenance.c 2011-12-20 11:41:33 +0000
> @@ -92,53 +93,48 @@
> static int handle_
> ...
David Martin (martin-lp) wrote : Posted in a previous version of this proposal | # |
Hi,
On Tue, Dec 20, 2011 at 6:50 PM, Miika Komu <email address hidden> wrote:
> Review: Needs Information
>
> 1. Did you test that memory is deallocated (valgrind) - optional, but extra good karma if you do this :)
Actually I did and it looks fine. There are only HIP_RETRANSMIT_
> 2. Does the scheme ignore retransmission of R1 messages (not really supposed to be resent)
R1s don't get buffered (hip_send_r1() sets the retransmit flag to zero when sending the packet) so they are not retransmitted as well. I did not touch this or to answer your question: yes, they are ignored.
What I did change though is R2 and U3. They are now not retransmitted anymore as they don't get explicitly acknowledged. A retransmission is basically triggered by the peer when they send I2 / U2 again.
> 3. Why to buffer to three messages?
It's more than one to retransmit the locators during UPDATEs. And three is more or less arbitrarily chosen by me. Two did not seem worth the effort of looping through it and four seems not needed? How many locators are common when using HIPL? On my test setup it's always only two... This can easily be changed by changing HIP_RETRANSMIT_
> Regarding to buffering, the state may change during retransmission and this causes the implementation to resend old messages in addition to new ones? If we're lucky, the peer will ignore UPDATE packets with old SPI numbers. However, the situation may be different in the BEX because there's no state.
I'm not sure whether I fully get your question. You mean for example when you trigger three UPDATEs in a row you would have three retransmissions? Once one of the UPDATEs has been processed the peer would ignore the older retransmissions (check_
Can you trigger another BEX during BEX? Can I force hipd to send another I1 when I'm in state R1_SENT for example? I did not test this.
In general the behaviour during BEX is basically unchanged though in this branch. When a I2, R1, R2, CLOSE or CLOSE_ACK comes in from the peer we remove all our retransmissions. On the host side a retransmission does not cause a state change. Retransmissions are simply putting a packet again on the wire, not more.
> A special (and supported) use case from base exchange: try to trigger the BEX simultaneously from both sides (i.e. break point both sides with gdb just after sending I1). I know the state machine can handle this but what happens to the retransmissions?
Actually I did try this and when I let two machines ping each other virtually at the same time the BEX sort of gets stuck and neither side can get any traffic through (this is not specific to this branch as it is the same on trunk).
In theory this situation is dealt with though. When receiving an I1 the host with the greater HIT removes its own I1 retransmissions.
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
On Wed, Dec 21, 2011 at 11:32:26AM +0100, Diego Biurrun wrote:
> On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
> > David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
> >
> > --- hipd/output.c 2011-11-10 10:53:21 +0000
> > +++ hipd/output.c 2011-12-20 11:41:33 +0000
> > @@ -1118,22 +1118,25 @@
> > const struct hip_common *msg,
> > struct hip_hadb_state *entry)
> > {
> > - int len = hip_get_
> > + int len = hip_get_
> > + struct hip_msg_retrans *retrans;
> >
> > if (!entry) {
> > return 0;
> > }
> >
> > + retrans = &entry-
> > +
> > /* Not reusing the old entry as the new packet may have different length */
> > + memset(
>
> see above
>
> > + memcpy(
> > + memcpy(
> > + memcpy(
The comment I intended to add here was that this looks as if it can be
done by assignments instead of memcpy.
Diego
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Hi,
On 22/12/11 00:22, Diego Biurrun wrote:
> On Wed, Dec 21, 2011 at 11:32:26AM +0100, Diego Biurrun wrote:
>> On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
>>> David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
>>>
>>> --- hipd/output.c 2011-11-10 10:53:21 +0000
>>> +++ hipd/output.c 2011-12-20 11:41:33 +0000
>>> @@ -1118,22 +1118,25 @@
>>> const struct hip_common *msg,
>>> struct hip_hadb_state *entry)
>>> {
>>> - int len = hip_get_
>>> + int len = hip_get_
>>> + struct hip_msg_retrans *retrans;
>>>
>>> if (!entry) {
>>> return 0;
>>> }
>>>
>>> + retrans =&entry-
>>> +
>>> /* Not reusing the old entry as the new packet may have different length */
>>> + memset(
>>
>> see above
>>
>>> + memcpy(
>>> + memcpy(
>>> + memcpy(
>
> The comment I intended to add here was that this looks as if it can be
> done by assignments instead of memcpy.
if you refer to IPv6 addresses, they have to be copied (no such thing as
128-bit integer). Anyway, the most elegant way is to use
ipv6_addr_copy() instead of memcpy().
David Martin (martin-lp) wrote : Posted in a previous version of this proposal | # |
Hi,
On Wed, Dec 21, 2011 at 11:32 AM, Diego Biurrun <email address hidden> wrote:
> review needs-fixing
>
> On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
>> David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
>>
>> --- hipd/hadb.c 2011-11-17 11:15:47 +0000
>> +++ hipd/hadb.c 2011-12-20 11:41:33 +0000
>> @@ -693,17 +693,25 @@
>> }
>>
>> - entry->
>>
>> /* Initialize module states */
>
> You should remove an excess empty line here.
fixed.
>> --- hipd/input.c 2011-12-09 09:32:56 +0000
>> +++ hipd/input.c 2011-12-20 11:41:33 +0000
>> @@ -1877,3 +1873,117 @@
>> +
>> +/**
>> + * Clear the given retransmission.
>> + * i.e. set the remaining retransmissions to zero and zero the buffer.
>> + *
>> + * @param retrans The retransmission to be cleared.
>> + */
>> +void hip_clear_
>> +{
>> + if (!retrans) {
>> + return;
>> + }
>> +
>> + retrans->count = 0;
>> + if (retrans->buf) {
>> + memset(
>
> sizeof(
Nope. It's just a pointer so that would not make much sense. But even referencing the struct does not seem right:
debug(hipd/
debug(hipd/
debug(hipd/
>> +/**
>> + * Update our buffered retransmissions after receiving the given packet.
>> + * This functions removes invalid retransmissions after a state change caused
>> + * by a received packet. For example after successfully receiving and handling
>> + * an I2 or R2 packet all our buffered packets are dropped.
>> + *
>> + * Call this function after successful handling of the incoming packet.
>> + *
>> + * @param packet_type The packet type of the control message (RFC 5201, 5.3.)
>> + * @param ha_state The host association state (RFC 5201, 4.4.1.)
>> + * @param ctx The packet context of the incoming transmission.
>> + *
>> + * @return always 0
>> + */
>
> Why always return 0?
Nothing unforeseen may happen that I deem important enough to break the handling of packets. I would make it void but the handle functions have to return an int.
>> +int hip_update_
>> + UNUSED const enum hip_state ha_state,
>> + struct hip_packet_context *const ctx)
>> +{
>> + struct hip_msg_retrans *retrans;
>> +
>> + HIP_ASSERT(ctx);
>> + HIP_ASSERT(
>> +
>> + /* When receiving an I1 there usually is no established state yet. */
>> + if (!ctx->hadb_entry) {
>> + return 0;
>> + }
>> +
>> + for (unsigned int i = 0; i < HIP_RETRANSMIT_
>> + retrans = &ctx->hadb_
>> +
>> + if (retrans->count == 0) {
>> + continue;
>> + }
>> +
>> + switch (hip_get_
>> + case HIP_I1:
>> + switch (hip_get_
David Martin (martin-lp) wrote : Posted in a previous version of this proposal | # |
Hi,
On Thu, Dec 22, 2011 at 8:42 AM, Miika Komu <email address hidden> wrote:
> On 22/12/11 00:22, Diego Biurrun wrote:
>>
>> On Wed, Dec 21, 2011 at 11:32:26AM +0100, Diego Biurrun wrote:
>>>
>>> On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
>>>>
>>>> David Martin has proposed merging
>>>> lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
>>>>
>>>> --- hipd/output.c 2011-11-10 10:53:21 +0000
>>>> +++ hipd/output.c 2011-12-20 11:41:33 +0000
>>>> @@ -1118,22 +1118,25 @@
>>>> const struct hip_common *msg,
>>>> struct hip_hadb_state *entry)
>>>> {
>>>> - int len = hip_get_
>>>> + int len = hip_get_
>>>> + struct hip_msg_retrans *retrans;
>>>>
>>>> if (!entry) {
>>>> return 0;
>>>> }
>>>>
>>>> + retrans =&entry-
>>>>
>>>> +
>>>> /* Not reusing the old entry as the new packet may have different
>>>> length */
>>>> + memset(
>>>
>>>
>>> see above
>>>
>>>> + memcpy(
>>>> + memcpy(
>>>> + memcpy(
>>
>>
>> The comment I intended to add here was that this looks as if it can be
>> done by assignments instead of memcpy.
>
>
> if you refer to IPv6 addresses, they have to be copied (no such thing as
> 128-bit integer). Anyway, the most elegant way is to use ipv6_addr_copy()
> instead of memcpy().
I don't think you can assign the buffer as they are independent. The retrans buffer slots are allocated at startup and the message comes wherever the caller allocates it from.
I've removed the needless variable indirection of the int len though and replaced the address memcpy() calls with ipv6_addr_copy().
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Hi,
On 21/12/11 12:46, David Martin wrote:
> Hi,
>
> On Tue, Dec 20, 2011 at 6:50 PM, Miika Komu<email address hidden> wrote:
>> Review: Needs Information
>>
>> 1. Did you test that memory is deallocated (valgrind) - optional,
>> but extra good karma if you do this :)
>
> Actually I did and it looks fine. There are only
> HIP_RETRANSMIT_
> so there is not that much to go wrong. Static memory ftw.
>
>> 2. Does the scheme ignore retransmission of R1 messages (not really
>> supposed to be resent)
>
> R1s don't get buffered (hip_send_r1() sets the retransmit flag to
> zero when sending the packet) so they are not retransmitted as well.
> I did not touch this or to answer your question: yes, they are
> ignored.
>
> What I did change though is R2 and U3. They are now not retransmitted
> anymore as they don't get explicitly acknowledged. A retransmission
> is basically triggered by the peer when they send I2 / U2 again.
>
>
>> 3. Why to buffer to three messages?
>
> It's more than one to retransmit the locators during UPDATEs. And
> three is more or less arbitrarily chosen by me. Two did not seem
> worth the effort of looping through it and four seems not needed? How
> many locators are common when using HIPL? On my test setup it's
> always only two... This can easily be changed by changing
> HIP_RETRANSMIT_
maybe I failed to understand something or should dig into the code
better. Are you saying that a buffered packet is a) retransmitted three
times or b) three packets can be queued?
Option a) makes sense, option b) doesn't make sense because the
retransmitted packets are identical (in most cases, see below).
>> Regarding to buffering, the state may change during retransmission
>> and this causes the implementation to resend old messages in
>> addition to new ones? If we're lucky, the peer will ignore UPDATE
>> packets with old SPI numbers. However, the situation may be
>> different in the BEX because there's no state.
>
> I'm not sure whether I fully get your question. You mean for example
> when you trigger three UPDATEs in a row you would have three
> retransmissions? Once one of the UPDATEs has been processed the peer
> would ignore the older retransmissions (check_
> would fail) and on our side the buffered retransmissions would be
> removed after receiving the U2 from the peer.
Regarding to option b), the packets can be different e.g. with UPDATEs.
It occurs that a host obtains new locators every now and then. If the
host has a queue of length of more than two, then it keeps sending an
old buffered set of locators in addition to the new set. While this is
not a big issue, it's completely unnecessary and should be avoided IMHO.
The easiest way to avoid this is to have queue of size one.
> Can you trigger another BEX during BEX? Can I force hipd to send
> another I1 when I'm in state R1_SENT for example? I did not test
> this.
No.
> In general the behaviour during BEX is basically unchanged though in
> this branch. When a I2, R1, R2, CLOSE or CLOSE_ACK comes in from the
> peer we remove all our retransmissions. On the host side a
> retransmissi...
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
On Thu, Dec 22, 2011 at 10:05:21AM +0000, David Martin wrote:
> On Wed, Dec 21, 2011 at 11:32 AM, Diego Biurrun <email address hidden> wrote:
> > On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
> >> David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
> >>
> >> --- hipd/input.c 2011-12-09 09:32:56 +0000
> >> +++ hipd/input.c 2011-12-20 11:41:33 +0000
> >> @@ -1877,3 +1873,117 @@
> >> +
> >> +/**
> >> + * Clear the given retransmission.
> >> + * i.e. set the remaining retransmissions to zero and zero the buffer.
> >> + *
> >> + * @param retrans The retransmission to be cleared.
> >> + */
> >> +void hip_clear_
> >> +{
> >> + if (!retrans) {
> >> + return;
> >> + }
> >> +
> >> + retrans->count = 0;
> >> + if (retrans->buf) {
> >> + memset(
> >
> > sizeof(
>
> Nope. It's just a pointer so that would not make much sense.
Sorry, sizeof(
> But even referencing the struct does not seem right:
>
> debug(hipd/
> debug(hipd/
> debug(hipd/
buf is a pointer to struct hip_common, which is
struct hip_common {
uint8_t payload_proto;
uint8_t payload_len;
uint8_t type_hdr;
uint8_t ver_res;
uint16_t checksum;
uint16_t control;
struct in6_addr hits; /**< Sender HIT */
struct in6_addr hitr; /**< Receiver HIT */
} __attribute_
so I guess the 40 bytes is about right.
So why 2048? It looks as though you are zeroing way beyond the field
you intend to initialize ...
> >> +/**
> >> + * Update our buffered retransmissions after receiving the given packet.
> >> + * This functions removes invalid retransmissions after a state change caused
> >> + * by a received packet. For example after successfully receiving and handling
> >> + * an I2 or R2 packet all our buffered packets are dropped.
> >> + *
> >> + * Call this function after successful handling of the incoming packet.
> >> + *
> >> + * @param packet_type The packet type of the control message (RFC 5201, 5.3.)
> >> + * @param ha_state The host association state (RFC 5201, 4.4.1.)
> >> + * @param ctx The packet context of the incoming transmission.
> >> + *
> >> + * @return always 0
> >> + */
> >
> > Why always return 0?
>
> Nothing unforeseen may happen that I deem important enough to break
> the handling of packets. I would make it void but the handle functions
> have to return an int.
OK, a short comment explaining this would be nice.
> >> --- hipd/maintenance.c 2011-12-16 13:37:33 +0000
> >> +++ hipd/maintenance.c 2011-12-20 11:41:33 +0000
> >> @@ -92,53 +93,48 @@
> >> static int handle_
> >> void *current_time)
> >> {
> >> + ...
David Martin (martin-lp) wrote : Posted in a previous version of this proposal | # |
Hi,
On Thu, Dec 22, 2011 at 1:31 PM, Diego Biurrun <email address hidden> wrote:
> On Thu, Dec 22, 2011 at 10:05:21AM +0000, David Martin wrote:
>> On Wed, Dec 21, 2011 at 11:32 AM, Diego Biurrun <email address hidden> wrote:
>> > On Tue, Dec 20, 2011 at 11:43:26AM +0000, David Martin wrote:
>> >> David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
>> >>
>> >> --- hipd/input.c 2011-12-09 09:32:56 +0000
>> >> +++ hipd/input.c 2011-12-20 11:41:33 +0000
>> >> @@ -1877,3 +1873,117 @@
>> >> +
>> >> +/**
>> >> + * Clear the given retransmission.
>> >> + * i.e. set the remaining retransmissions to zero and zero the buffer.
>> >> + *
>> >> + * @param retrans The retransmission to be cleared.
>> >> + */
>> >> +void hip_clear_
>> >> +{
>> >> + if (!retrans) {
>> >> + return;
>> >> + }
>> >> +
>> >> + retrans->count = 0;
>> >> + if (retrans->buf) {
>> >> + memset(
>> >
>> > sizeof(
>>
>> Nope. It's just a pointer so that would not make much sense.
>
> Sorry, sizeof(
>
>> But even referencing the struct does not seem right:
>>
>> debug(hipd/
>> debug(hipd/
>> debug(hipd/
>
> buf is a pointer to struct hip_common, which is
>
> struct hip_common {
> uint8_t payload_proto;
> uint8_t payload_len;
> uint8_t type_hdr;
> uint8_t ver_res;
> uint16_t checksum;
> uint16_t control;
> struct in6_addr hits; /**< Sender HIT */
> struct in6_addr hitr; /**< Receiver HIT */
> } __attribute_
>
> so I guess the 40 bytes is about right.
>
> So why 2048? It looks as though you are zeroing way beyond the field
> you intend to initialize ...
You are right and wrong. 40 bytes is wrong as this would only be the size of the message header. You have to keep in mind that there's payload as well. You are right as 2048 is the maximum size and a sort of pessimistic approach. I've changed it so that it zeros only the actual message size. The queuing function uses hip_get_
>> >> +/**
>> >> + * Update our buffered retransmissions after receiving the given packet.
>> >> + * This functions removes invalid retransmissions after a state change caused
>> >> + * by a received packet. For example after successfully receiving and handling
>> >> + * an I2 or R2 packet all our buffered packets are dropped.
>> >> + *
>> >> + * Call this function after successful handling of the incoming packet.
>> >> + *
>> >> + * @param packet_type The packet type of the control message (RFC 5201, 5.3.)
>> >> + * @param ha_state The host association sta...
David Martin (martin-lp) wrote : Posted in a previous version of this proposal | # |
Hi,
On Thu, Dec 22, 2011 at 11:45 AM, Miika Komu <email address hidden> wrote:
> On 21/12/11 12:46, David Martin wrote:
>> On Tue, Dec 20, 2011 at 6:50 PM, Miika Komu<email address hidden> wrote:
>>> 3. Why to buffer to three messages?
>>
>>
>> It's more than one to retransmit the locators during UPDATEs. And
>> three is more or less arbitrarily chosen by me. Two did not seem
>> worth the effort of looping through it and four seems not needed? How
>> many locators are common when using HIPL? On my test setup it's
>> always only two... This can easily be changed by changing
>> HIP_RETRANSMIT_
>
>
> maybe I failed to understand something or should dig into the code better.
> Are you saying that a buffered packet is a) retransmitted three times or b)
> three packets can be queued?
>
> Option a) makes sense, option b) doesn't make sense because the
> retransmitted packets are identical (in most cases, see below).
We are doing option b) in this branch. Well, are they identical? The destination of the buffered U2 packets differ because of the locators so this is not true, no?
>>> Regarding to buffering, the state may change during retransmission
>>> and this causes the implementation to resend old messages in
>>> addition to new ones? If we're lucky, the peer will ignore UPDATE
>>> packets with old SPI numbers. However, the situation may be
>>> different in the BEX because there's no state.
>>
>>
>> I'm not sure whether I fully get your question. You mean for example
>> when you trigger three UPDATEs in a row you would have three
>> retransmissions? Once one of the UPDATEs has been processed the peer
>> would ignore the older retransmissions (check_
>> would fail) and on our side the buffered retransmissions would be
>> removed after receiving the U2 from the peer.
>
>
> Regarding to option b), the packets can be different e.g. with UPDATEs. It
> occurs that a host obtains new locators every now and then. If the host has
> a queue of length of more than two, then it keeps sending an old buffered
> set of locators in addition to the new set. While this is not a big issue,
> it's completely unnecessary and should be avoided IMHO. The easiest way to
> avoid this is to have queue of size one.
Setting the queue to size to one would completely defeat its point though. How often does such a locator change happen? I guess in theory it may happen that an UPDATE is triggered and lost, the host obtains a new locator and another UPDATE is triggered which is lost again. Then you would actually retransmit both UPDATEs with different locators.
A solution may be to remove older buffered U1 packets when a new UPDATE is triggered. I may change that if necessary or desired.
>> Can you trigger another BEX during BEX? Can I force hipd to send
>> another I1 when I'm in state R1_SENT for example? I did not test
>> this.
>
>
> No.
Ok, so we do not have a problem here.
>>> A special (and supported) use case from base exchange: try to
>>> trigger the BEX simultaneously from both sides (i.e. break point
>>> both sides with gdb just after sending I1). I know the state
>>> machine can handle this but what happens to the retransmissions?
>>...
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Hi,
On 12/29/2011 01:01 PM, David Martin wrote:
> Hi,
>
> On Thu, Dec 22, 2011 at 11:45 AM, Miika Komu<email address hidden>
> wrote:
>> On 21/12/11 12:46, David Martin wrote:
>>> On Tue, Dec 20, 2011 at 6:50 PM, Miika Komu<email address hidden>
>>> wrote:
>
>>>> 3. Why to buffer to three messages?
>>>
>>>
>>> It's more than one to retransmit the locators during UPDATEs.
>>> And three is more or less arbitrarily chosen by me. Two did not
>>> seem worth the effort of looping through it and four seems not
>>> needed? How many locators are common when using HIPL? On my test
>>> setup it's always only two... This can easily be changed by
>>> changing HIP_RETRANSMIT_
>>
>>
>> maybe I failed to understand something or should dig into the code
>> better. Are you saying that a buffered packet is a) retransmitted
>> three times or b) three packets can be queued?
>>
>> Option a) makes sense, option b) doesn't make sense because the
>> retransmitted packets are identical (in most cases, see below).
>
> We are doing option b) in this branch. Well, are they identical? The
> destination of the buffered U2 packets differ because of the locators
> so this is not true, no?
the retransmitted packages are different only in exceptional
circumstances. Similarly, the destination is usually the same because
there is one retransmission queue per host association - right?
Note: the destination can actually change with the shotgun extension
because it sends an UPDATE to all known peer addresses.
>>>> Regarding to buffering, the state may change during
>>>> retransmission and this causes the implementation to resend old
>>>> messages in addition to new ones? If we're lucky, the peer will
>>>> ignore UPDATE packets with old SPI numbers. However, the
>>>> situation may be different in the BEX because there's no
>>>> state.
>>>
>>>
>>> I'm not sure whether I fully get your question. You mean for
>>> example when you trigger three UPDATEs in a row you would have
>>> three retransmissions? Once one of the UPDATEs has been processed
>>> the peer would ignore the older retransmissions
>>> (check_
>>> buffered retransmissions would be removed after receiving the U2
>>> from the peer.
>>
>>
>> Regarding to option b), the packets can be different e.g. with
>> UPDATEs. It occurs that a host obtains new locators every now and
>> then. If the host has a queue of length of more than two, then it
>> keeps sending an old buffered set of locators in addition to the
>> new set. While this is not a big issue, it's completely unnecessary
>> and should be avoided IMHO. The easiest way to avoid this is to
>> have queue of size one.
>
> Setting the queue to size to one would completely defeat its point
> though.
What is the point of having a queue size of more than one actually? Or
is that that the buffer size determines the number of retransmissions?
> How often does such a locator change happen?
Seldom by default because hipd reacts to locator changes with an
intended delay to accumulate the changes.
> I guess in
> theory it may happen that an UPDATE is triggered and lost, the host
> obtains a new locator and another UPDA...
David Martin (martin-lp) wrote : | # |
Hey,
On Thu, Dec 29, 2011 at 12:29 PM, Miika Komu <email address hidden> wrote:
> On 12/29/2011 01:01 PM, David Martin wrote:
>> On Thu, Dec 22, 2011 at 11:45 AM, Miika Komu<email address hidden>
>>> On 21/12/11 12:46, David Martin wrote:
>>>> On Tue, Dec 20, 2011 at 6:50 PM, Miika Komu<email address hidden>
>>>>> 3. Why to buffer to three messages?
>>>>
>>>> It's more than one to retransmit the locators during UPDATEs.
>>>> And three is more or less arbitrarily chosen by me. Two did not
>>>> seem worth the effort of looping through it and four seems not
>>>> needed? How many locators are common when using HIPL? On my test
>>>> setup it's always only two... This can easily be changed by
>>>> changing HIP_RETRANSMIT_
>>>
>>> maybe I failed to understand something or should dig into the code
>>> better. Are you saying that a buffered packet is a) retransmitted
>>> three times or b) three packets can be queued?
>>>
>>> Option a) makes sense, option b) doesn't make sense because the
>>> retransmitted packets are identical (in most cases, see below).
>>
>>
>> We are doing option b) in this branch. Well, are they identical? The
>> destination of the buffered U2 packets differ because of the locators
>> so this is not true, no?
>
> the retransmitted packages are different only in exceptional
> circumstances. Similarly, the destination is usually the same because
> there is one retransmission queue per host association - right?
I'm not sure whether we are talking at cross-purposes right now. :) In principle it's quite simple:
Yes, retransmissions are handled on a per host association basis. At the moment in trunk we have got a single maximum message sized buffer for each host association. When we send a message (which is supposed to be retransmitted when it does not reach its destination) it gets copied to this buffer. Every subsequent message gets copied into the same buffer overwriting the previous one. This is fine for BEX as packets are send on their own and we do not care about previous ones. As far as I understand it it is different for UPDATEs. The first UPDATE packet has got a list of locators. The second UPDATE packet from the peer is send to all of these locators. In the case we send to 3 locators, the first and second transmission would never be retransmitted as they get overwritten by the subsequent ones.
Now what this branch does is instead of having at max a single message per HA buffered we now can buffer up to three (set by a #define and open for discussion which value is best) messages per HA. This means that in case of the second UPDATE packet all transmissions to the different locators are retransmitted and not just the last one. This change for UPDATE retransmissions is the real benefit of increasing the queue size. It does not make a difference for normal BEX.
> Note: the destination can actually change with the shotgun extension because
> it sends an UPDATE to all known peer addresses.
If I see it right in hip_send_pkt() in output.c all packets get transmitted to all known addresses when the shotgun extension is used. This would benefit of a greater queue size as well then as then all packets to the different addresses...
Miika Komu (miika-iki) wrote : | # |
Thanks, I understood now. Good work!
Diego Biurrun (diego-biurrun) wrote : | # |
review abstain
I leave the decision to Miika, who still had some concerns.
Below are some minor issues I noticed; at least the typo
should be addressed before merging.
On Thu, Dec 29, 2011 at 11:15:31AM +0000, David Martin wrote:
> David Martin has proposed merging lp:~martin-lp/hipl/hipl_retransmissions into lp:hipl.
>
> Requested reviews:
> Diego Biurrun (diego-biurrun)
> Miika Komu (miika-iki)
>
> --- hipd/input.c 2011-12-09 09:32:56 +0000
> +++ hipd/input.c 2011-12-29 11:14:24 +0000
> @@ -1877,3 +1873,121 @@
>
> +/**
> + * Update our buffered retransmissions after receiving the given packet.
> + * This functions removes invalid retransmissions after a state change caused
> + * by a received packet. For example after successfully receiving and handling
> + * an I2 or R2 packet all our buffered packets are dropped.
> + *
> + * Call this function after successful handling of the incoming packet.
> + *
> + * @param packet_type The packet type of the control message (RFC 5201, 5.3.)
> + * @param ha_state The host association state (RFC 5201, 4.4.1.)
> + * @param ctx The packet context of the incoming transmission.
> + *
> + * @return Always 0. Nothing onforeseen may happen here which is important
_u_nforeseen
> --- hipd/maintenance.c 2011-12-21 10:54:26 +0000
> +++ hipd/maintenance.c 2011-12-29 11:14:24 +0000
> @@ -89,55 +90,50 @@
> +static int handle_
> + void *current_time)
> {
> +
> + for (i = 0; i < HIP_RETRANSMIT_
> + retrans = &entry-
> + HIP_RETRANSMIT_
> +
> + /* check if the last transmission was at least RETRANSMIT_WAIT seconds ago */
> + if (*now - HIP_RETRANSMIT_WAIT > retrans-
> + if (retrans->count > 0) {
> + /* @todo: verify that this works over slow ADSL line */
> + if (hip_send_
> + &retrans->daddr,
> + entry->nat_mode ? hip_get_
> + entry->
> + retrans->buf,
> + entry, 0) < 0) {
> + HIP_ERROR("Failed to retransmit packet of type %d.\n",
> + hip_get_
> + err = -1;
> + }
> +
> + /* Set entry state, if previous state was unassociated
> + * and type is I1. */
> + if (!err && hip_get_
> + entry->state == HIP_STATE_
> + HIP_DEBUG("Resent I1 succcesfully\n");
> + entry->state = HIP_STATE_I1_SENT;
> + }
Instead of testing err you could move this into the previous if-block.
That would read more natural to me.
> + retrans->count--;
> + time(&retrans-
> } else {
> + if (hip_get_m...
- 6234. By David Martin
-
Fix typo in hip_update_
retransmissions () doxygen documentation. - 6235. By David Martin
-
Make if-conditions in handle_
retransmissions () more reasonable. Do not check for the err value twice and use else if when there is only
a single if condition in the else case.
David Martin (martin-lp) wrote : | # |
I've fixed the two issues mentioned by Diego in revisions 6234f. Should I start another review or is it good as is?
Miika Komu (miika-iki) wrote : | # |
In my opinion, go ahead and merge.
David Martin (martin-lp) wrote : | # |
Ok, done.
Preview Diff
1 | === modified file 'hipd/hadb.c' |
2 | --- hipd/hadb.c 2011-12-28 15:52:14 +0000 |
3 | +++ hipd/hadb.c 2011-12-29 15:06:25 +0000 |
4 | @@ -693,17 +693,24 @@ |
5 | get_random_bytes(&entry->spi_inbound_current, |
6 | sizeof(entry->spi_inbound_current)); |
7 | |
8 | - if (!(entry->hip_msg_retrans.buf = calloc(1, HIP_MAX_NETWORK_PACKET))) { |
9 | - return -ENOMEM; |
10 | + entry->next_retrans_slot = 0; |
11 | + for (unsigned int i = 0; i < HIP_RETRANSMIT_QUEUE_SIZE; i++) { |
12 | + if (!(entry->hip_msg_retrans[i].buf = calloc(1, HIP_MAX_NETWORK_PACKET))) { |
13 | + for (unsigned int j = 0; j < i; j++) { |
14 | + free(entry->hip_msg_retrans[j].buf); |
15 | + } |
16 | + return -ENOMEM; |
17 | + } |
18 | + entry->hip_msg_retrans[i].count = 0; |
19 | } |
20 | |
21 | - entry->hip_msg_retrans.count = 0; |
22 | - |
23 | /* Initialize module states */ |
24 | entry->hip_modular_state = lmod_init_state(); |
25 | if (entry->hip_modular_state == NULL) { |
26 | HIP_ERROR("Failed to initialize modular state.\n"); |
27 | - free(entry->hip_msg_retrans.buf); |
28 | + for (unsigned int i = 0; i < HIP_RETRANSMIT_QUEUE_SIZE; i++) { |
29 | + free(entry->hip_msg_retrans[i].buf); |
30 | + } |
31 | return -1; |
32 | } |
33 | lmod_init_state_items(entry->hip_modular_state); |
34 | @@ -823,7 +830,9 @@ |
35 | /* Delete SAs */ |
36 | |
37 | free(ha->dh_shared_key); |
38 | - free(ha->hip_msg_retrans.buf); |
39 | + for (i = 0; i < HIP_RETRANSMIT_QUEUE_SIZE; i++) { |
40 | + free(ha->hip_msg_retrans[i].buf); |
41 | + } |
42 | if (ha->peer_pub) { |
43 | switch (hip_get_host_id_algo(ha->peer_pub)) { |
44 | case HIP_HI_RSA: |
45 | |
46 | === modified file 'hipd/init.c' |
47 | --- hipd/init.c 2011-12-12 14:30:43 +0000 |
48 | +++ hipd/init.c 2011-12-29 15:06:25 +0000 |
49 | @@ -561,31 +561,40 @@ |
50 | |
51 | hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_check_i1, 20000); |
52 | hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_handle_i1, 30000); |
53 | + hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_update_retransmissions, 35000); |
54 | hip_register_handle_function(HIP_I1, HIP_STATE_UNASSOCIATED, &hip_send_r1, 40000); |
55 | hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_check_i1, 20000); |
56 | hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_handle_i1, 30000); |
57 | + hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_update_retransmissions, 35000); |
58 | hip_register_handle_function(HIP_I1, HIP_STATE_I1_SENT, &hip_send_r1, 40000); |
59 | hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_check_i1, 20000); |
60 | hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_handle_i1, 30000); |
61 | + hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_update_retransmissions, 35000); |
62 | hip_register_handle_function(HIP_I1, HIP_STATE_I2_SENT, &hip_send_r1, 40000); |
63 | hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_check_i1, 20000); |
64 | hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_handle_i1, 30000); |
65 | + hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_update_retransmissions, 35000); |
66 | hip_register_handle_function(HIP_I1, HIP_STATE_R2_SENT, &hip_send_r1, 40000); |
67 | hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_check_i1, 20000); |
68 | hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_handle_i1, 30000); |
69 | + hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 35000); |
70 | hip_register_handle_function(HIP_I1, HIP_STATE_ESTABLISHED, &hip_send_r1, 40000); |
71 | hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_check_i1, 20000); |
72 | hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_handle_i1, 30000); |
73 | + hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_update_retransmissions, 35000); |
74 | hip_register_handle_function(HIP_I1, HIP_STATE_CLOSING, &hip_send_r1, 40000); |
75 | hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_check_i1, 20000); |
76 | hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_handle_i1, 30000); |
77 | + hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_update_retransmissions, 35000); |
78 | hip_register_handle_function(HIP_I1, HIP_STATE_CLOSED, &hip_send_r1, 40000); |
79 | hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_check_i1, 20000); |
80 | hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_handle_i1, 30000); |
81 | + hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_update_retransmissions, 35000); |
82 | hip_register_handle_function(HIP_I1, HIP_STATE_NONE, &hip_send_r1, 40000); |
83 | |
84 | hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_check_i2, 20000); |
85 | hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_handle_i2, 30000); |
86 | + hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_update_retransmissions, 30250); |
87 | hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_setup_ipsec_sa, 30500); |
88 | hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_create_r2, 40000); |
89 | hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_add_rvs_reg_from, 41000); |
90 | @@ -594,6 +603,7 @@ |
91 | hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED, &hip_send_r2, 50000); |
92 | hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_check_i2, 20000); |
93 | hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_handle_i2, 30000); |
94 | + hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_update_retransmissions, 30250); |
95 | hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_setup_ipsec_sa, 30500); |
96 | hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_create_r2, 40000); |
97 | hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT, &hip_add_rvs_reg_from, 41000); |
98 | @@ -603,6 +613,7 @@ |
99 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_check_i2, 20000); |
100 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2_in_i2_sent, 21000); |
101 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_handle_i2, 30000); |
102 | + hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30250); |
103 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_setup_ipsec_sa, 30500); |
104 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_create_r2, 40000); |
105 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_add_rvs_reg_from, 41000); |
106 | @@ -611,6 +622,7 @@ |
107 | hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT, &hip_send_r2, 50000); |
108 | hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_check_i2, 20000); |
109 | hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_handle_i2, 30000); |
110 | + hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_update_retransmissions, 30250); |
111 | hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_setup_ipsec_sa, 30500); |
112 | hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_create_r2, 40000); |
113 | hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_add_rvs_reg_from, 41000); |
114 | @@ -619,6 +631,7 @@ |
115 | hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT, &hip_send_r2, 50000); |
116 | hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_check_i2, 20000); |
117 | hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_handle_i2, 30000); |
118 | + hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 30250); |
119 | hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_setup_ipsec_sa, 30500); |
120 | hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_create_r2, 40000); |
121 | hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_add_rvs_reg_from, 41000); |
122 | @@ -627,6 +640,7 @@ |
123 | hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED, &hip_send_r2, 50000); |
124 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_check_i2, 20000); |
125 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_handle_i2, 30000); |
126 | + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_update_retransmissions, 30250); |
127 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_setup_ipsec_sa, 30500); |
128 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_create_r2, 40000); |
129 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_add_rvs_reg_from, 41000); |
130 | @@ -635,6 +649,7 @@ |
131 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSING, &hip_send_r2, 50000); |
132 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_check_i2, 20000); |
133 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_handle_i2, 30000); |
134 | + hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_update_retransmissions, 30250); |
135 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_setup_ipsec_sa, 30500); |
136 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_create_r2, 40000); |
137 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_add_rvs_reg_from, 41000); |
138 | @@ -643,6 +658,7 @@ |
139 | hip_register_handle_function(HIP_I2, HIP_STATE_CLOSED, &hip_send_r2, 50000); |
140 | hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_check_i2, 20000); |
141 | hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_handle_i2, 30000); |
142 | + hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_update_retransmissions, 30250); |
143 | hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_setup_ipsec_sa, 30500); |
144 | hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_create_r2, 40000); |
145 | hip_register_handle_function(HIP_I2, HIP_STATE_NONE, &hip_add_rvs_reg_from, 41000); |
146 | @@ -652,6 +668,7 @@ |
147 | |
148 | hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_check_r1, 20000); |
149 | hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_r1, 30000); |
150 | + hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_update_retransmissions, 30500); |
151 | hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_build_esp_info, 31000); |
152 | hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_build_solution, 32000); |
153 | hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_handle_diffie_hellman, 33000); |
154 | @@ -663,6 +680,7 @@ |
155 | hip_register_handle_function(HIP_R1, HIP_STATE_I1_SENT, &hip_send_i2, 50000); |
156 | hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_check_r1, 20000); |
157 | hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_r1, 30000); |
158 | + hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30500); |
159 | hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_build_esp_info, 31000); |
160 | hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_build_solution, 32000); |
161 | hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_handle_diffie_hellman, 33000); |
162 | @@ -674,6 +692,7 @@ |
163 | hip_register_handle_function(HIP_R1, HIP_STATE_I2_SENT, &hip_send_i2, 50000); |
164 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_check_r1, 20000); |
165 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_r1, 30000); |
166 | + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_update_retransmissions, 30500); |
167 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_build_esp_info, 31000); |
168 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_build_solution, 32000); |
169 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_handle_diffie_hellman, 33000); |
170 | @@ -685,6 +704,7 @@ |
171 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSING, &hip_send_i2, 50000); |
172 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_check_r1, 20000); |
173 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_r1, 30000); |
174 | + hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_update_retransmissions, 30500); |
175 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_build_esp_info, 31000); |
176 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_build_solution, 32000); |
177 | hip_register_handle_function(HIP_R1, HIP_STATE_CLOSED, &hip_handle_diffie_hellman, 33000); |
178 | @@ -697,6 +717,7 @@ |
179 | |
180 | hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_check_r2, 20000); |
181 | hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_handle_r2, 30000); |
182 | + hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_update_retransmissions, 30250); |
183 | hip_register_handle_function(HIP_R2, HIP_STATE_I2_SENT, &hip_setup_ipsec_sa, 30500); |
184 | |
185 | hip_register_handle_function(HIP_NOTIFY, HIP_STATE_I1_SENT, &hip_check_notify, 20000); |
186 | @@ -712,18 +733,22 @@ |
187 | hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, &hip_check_notify, 20000); |
188 | hip_register_handle_function(HIP_NOTIFY, HIP_STATE_CLOSED, &hip_handle_notify, 30000); |
189 | |
190 | - hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_check_packet, 20000); |
191 | - hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_create_response, 30000); |
192 | - hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_send_response, 40000); |
193 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_check_packet, 20000); |
194 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_update_retransmissions, 25000); |
195 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_create_response, 30000); |
196 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_ESTABLISHED, &hip_close_send_response, 40000); |
197 | |
198 | - hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_check_packet, 20000); |
199 | - hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_create_response, 30000); |
200 | - hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_send_response, 40000); |
201 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_check_packet, 20000); |
202 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_update_retransmissions, 25000); |
203 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_create_response, 30000); |
204 | + hip_register_handle_function(HIP_CLOSE, HIP_STATE_CLOSING, &hip_close_send_response, 40000); |
205 | |
206 | hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_close_ack_check_packet, 20000); |
207 | + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_update_retransmissions, 25000); |
208 | hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSING, &hip_close_ack_handle_packet, 30000); |
209 | |
210 | hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_close_ack_check_packet, 20000); |
211 | + hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_update_retransmissions, 25000); |
212 | hip_register_handle_function(HIP_CLOSE_ACK, HIP_STATE_CLOSED, &hip_close_ack_handle_packet, 30000); |
213 | |
214 | hip_register_handle_function(HIP_LUPDATE, HIP_STATE_ESTABLISHED, &esp_prot_handle_light_update, 20000); |
215 | |
216 | === modified file 'hipd/input.c' |
217 | --- hipd/input.c 2011-12-09 09:32:56 +0000 |
218 | +++ hipd/input.c 2011-12-29 15:06:25 +0000 |
219 | @@ -58,6 +58,7 @@ |
220 | #include "lib/core/state.h" |
221 | #include "lib/core/transform.h" |
222 | #include "lib/tool/xfrmapi.h" |
223 | +#include "modules/update/hipd/update.h" |
224 | #include "config.h" |
225 | #include "cookie.h" |
226 | #include "dh.h" |
227 | @@ -1113,8 +1114,6 @@ |
228 | hip_perf_stop_benchmark(perf_set, PERF_BASE); |
229 | hip_perf_write_benchmark(perf_set, PERF_BASE); |
230 | #endif |
231 | - ctx->hadb_entry->hip_msg_retrans.count = 0; |
232 | - memset(ctx->hadb_entry->hip_msg_retrans.buf, 0, HIP_MAX_NETWORK_PACKET); |
233 | |
234 | if (ctx->hadb_entry->state == HIP_STATE_ESTABLISHED) { |
235 | HIP_DEBUG("Send response to firewall.\n"); |
236 | @@ -1695,9 +1694,6 @@ |
237 | ctx->hadb_entry->state = HIP_STATE_ESTABLISHED; |
238 | HIP_INFO("Reached %s state\n", hip_state_str(ctx->hadb_entry->state)); |
239 | |
240 | - ctx->hadb_entry->hip_msg_retrans.count = 0; |
241 | - memset(ctx->hadb_entry->hip_msg_retrans.buf, 0, HIP_MAX_NETWORK_PACKET); |
242 | - |
243 | out_err: |
244 | if (err) { |
245 | ctx->error = err; |
246 | @@ -1877,3 +1873,121 @@ |
247 | |
248 | return err; |
249 | } |
250 | + |
251 | +/** |
252 | + * Clear the given retransmission. |
253 | + * i.e. set the remaining retransmissions to zero and zero the buffer. |
254 | + * |
255 | + * @param retrans The retransmission to be cleared. |
256 | + */ |
257 | +void hip_clear_retransmission(struct hip_msg_retrans *const retrans) |
258 | +{ |
259 | + if (!retrans) { |
260 | + return; |
261 | + } |
262 | + |
263 | + retrans->count = 0; |
264 | + if (retrans->buf) { |
265 | + memset(retrans->buf, 0, hip_get_msg_total_len(retrans->buf)); |
266 | + } |
267 | +} |
268 | + |
269 | +/** |
270 | + * Decide whether the given UPDATE retransmission is still valid with regard to |
271 | + * the incoming message. For example a buffered U1 packet is invalidated when a |
272 | + * fresh U2 comes in. |
273 | + * |
274 | + * @param ctx The packet context of the incoming transmission. |
275 | + * @param retrans The retransmission in question. |
276 | + * @return True if given retransmission is invalid. |
277 | + * False else. |
278 | + */ |
279 | +static bool update_retrans_is_invalid(struct hip_packet_context *const ctx, |
280 | + struct hip_msg_retrans *const retrans) |
281 | +{ |
282 | + if (!ctx || !retrans) { |
283 | + return false; |
284 | + } |
285 | + |
286 | + switch (hip_classify_update_type(ctx->input_msg)) { |
287 | + case SECOND_UPDATE_PACKET: |
288 | + return hip_classify_update_type(retrans->buf) == FIRST_UPDATE_PACKET; |
289 | + |
290 | + case THIRD_UPDATE_PACKET: |
291 | + return hip_classify_update_type(retrans->buf) == SECOND_UPDATE_PACKET; |
292 | + |
293 | + default: |
294 | + return false; |
295 | + } |
296 | +} |
297 | + |
298 | +/** |
299 | + * Update our buffered retransmissions after receiving the given packet. |
300 | + * This functions removes invalid retransmissions after a state change caused |
301 | + * by a received packet. For example after successfully receiving and handling |
302 | + * an I2 or R2 packet all our buffered packets are dropped. |
303 | + * |
304 | + * Call this function after successful handling of the incoming packet. |
305 | + * |
306 | + * @param packet_type The packet type of the control message (RFC 5201, 5.3.) |
307 | + * @param ha_state The host association state (RFC 5201, 4.4.1.) |
308 | + * @param ctx The packet context of the incoming transmission. |
309 | + * |
310 | + * @return Always 0. Nothing unforeseen may happen here which is important |
311 | + * enough to break the packet processing. Unhandled incoming message |
312 | + * types are simply ignored. Handle functions have to return an int |
313 | + * though so always 0 it is. |
314 | + */ |
315 | +int hip_update_retransmissions(UNUSED const uint8_t packet_type, |
316 | + UNUSED const enum hip_state ha_state, |
317 | + struct hip_packet_context *const ctx) |
318 | +{ |
319 | + struct hip_msg_retrans *retrans; |
320 | + |
321 | + HIP_ASSERT(ctx); |
322 | + HIP_ASSERT(ctx->input_msg); |
323 | + |
324 | + /* When receiving an I1 there usually is no established state yet. */ |
325 | + if (!ctx->hadb_entry) { |
326 | + return 0; |
327 | + } |
328 | + |
329 | + for (unsigned int i = 0; i < HIP_RETRANSMIT_QUEUE_SIZE; i++) { |
330 | + retrans = &ctx->hadb_entry->hip_msg_retrans[i]; |
331 | + |
332 | + if (retrans->count == 0) { |
333 | + continue; |
334 | + } |
335 | + |
336 | + switch (hip_get_msg_type(ctx->input_msg)) { |
337 | + case HIP_I1: |
338 | + /* We only remove our sent I1s when we have got a greater HIT |
339 | + * than the peer (ref. RFC 5201, 4.4.2). */ |
340 | + if (hip_get_msg_type(retrans->buf) == HIP_I1 && |
341 | + hip_hit_is_bigger(&ctx->hadb_entry->hit_our, &ctx->hadb_entry->hit_peer)) { |
342 | + hip_clear_retransmission(retrans); |
343 | + } |
344 | + break; |
345 | + |
346 | + case HIP_I2: |
347 | + case HIP_R1: |
348 | + case HIP_R2: |
349 | + case HIP_CLOSE: |
350 | + case HIP_CLOSE_ACK: |
351 | + hip_clear_retransmission(retrans); |
352 | + break; |
353 | + |
354 | + case HIP_UPDATE: |
355 | + if (update_retrans_is_invalid(ctx, retrans)) { |
356 | + hip_clear_retransmission(retrans); |
357 | + } |
358 | + break; |
359 | + |
360 | + /* We do not act on other message types like Light UPDATE for example. */ |
361 | + default: |
362 | + break; |
363 | + } |
364 | + } |
365 | + |
366 | + return 0; |
367 | +} |
368 | |
369 | === modified file 'hipd/input.h' |
370 | --- hipd/input.h 2011-11-25 17:56:24 +0000 |
371 | +++ hipd/input.h 2011-12-29 15:06:25 +0000 |
372 | @@ -127,4 +127,10 @@ |
373 | UNUSED const enum hip_state ha_state, |
374 | struct hip_packet_context *ctx); |
375 | |
376 | +void hip_clear_retransmission(struct hip_msg_retrans *const retrans); |
377 | + |
378 | +int hip_update_retransmissions(UNUSED const uint8_t packet_type, |
379 | + UNUSED const enum hip_state ha_state, |
380 | + struct hip_packet_context *const ctx); |
381 | + |
382 | #endif /* HIPL_HIPD_INPUT_H */ |
383 | |
384 | === modified file 'hipd/maintenance.c' |
385 | --- hipd/maintenance.c 2011-12-21 10:54:26 +0000 |
386 | +++ hipd/maintenance.c 2011-12-29 15:06:25 +0000 |
387 | @@ -60,6 +60,7 @@ |
388 | #include "hidb.h" |
389 | #include "hipd.h" |
390 | #include "init.h" |
391 | +#include "input.h" |
392 | #include "output.h" |
393 | #include "maintenance.h" |
394 | |
395 | @@ -89,55 +90,48 @@ |
396 | * @param current_time current time |
397 | * @return zero on success or negative on failure |
398 | */ |
399 | -static int handle_retransmission(struct hip_hadb_state *entry, |
400 | - void *current_time) |
401 | +static int handle_retransmissions(struct hip_hadb_state *entry, |
402 | + void *current_time) |
403 | { |
404 | - int err = 0; |
405 | - time_t *now = current_time; |
406 | - |
407 | - if (entry->hip_msg_retrans.count == 0) { |
408 | - goto out_err; |
409 | - } |
410 | - |
411 | - /* check if the last transmission was at least RETRANSMIT_WAIT seconds ago */ |
412 | - if (*now - HIP_RETRANSMIT_WAIT > entry->hip_msg_retrans.last_transmit) { |
413 | - if (entry->hip_msg_retrans.count > 0 && |
414 | - ((entry->state != HIP_STATE_ESTABLISHED && entry->retrans_state != entry->state) || |
415 | - entry->light_update_retrans == 1)) { |
416 | - HIP_DEBUG("state=%d, retrans_state=%d\n", entry->state, entry->retrans_state); |
417 | - |
418 | - /* @todo: verify that this works over slow ADSL line */ |
419 | - err = hip_send_pkt(&entry->hip_msg_retrans.saddr, |
420 | - &entry->hip_msg_retrans.daddr, |
421 | - entry->nat_mode ? hip_get_local_nat_udp_port() : 0, |
422 | - entry->peer_udp_port, |
423 | - entry->hip_msg_retrans.buf, |
424 | - entry, 0); |
425 | - |
426 | - /* Set entry state, if previous state was unassociated |
427 | - * and type is I1. */ |
428 | - if (!err && hip_get_msg_type(entry->hip_msg_retrans.buf) |
429 | - == HIP_I1 && entry->state == HIP_STATE_UNASSOCIATED) { |
430 | - HIP_DEBUG("Resent I1 succcesfully\n"); |
431 | - entry->state = HIP_STATE_I1_SENT; |
432 | - } |
433 | - |
434 | - entry->hip_msg_retrans.count--; |
435 | - time(&entry->hip_msg_retrans.last_transmit); |
436 | - } else { |
437 | - entry->hip_msg_retrans.count = 0; |
438 | - memset(entry->hip_msg_retrans.buf, 0, HIP_MAX_NETWORK_PACKET); |
439 | - |
440 | - if (entry->state == HIP_STATE_ESTABLISHED) { |
441 | - entry->retrans_state = HIP_STATE_NONE; |
442 | - } else { |
443 | - entry->retrans_state = entry->state; |
444 | + int err = 0, i = 0; |
445 | + struct hip_msg_retrans *retrans; |
446 | + time_t *now = current_time; |
447 | + |
448 | + for (i = 0; i < HIP_RETRANSMIT_QUEUE_SIZE; i++) { |
449 | + retrans = &entry->hip_msg_retrans[(entry->next_retrans_slot + i) % |
450 | + HIP_RETRANSMIT_QUEUE_SIZE]; |
451 | + |
452 | + /* check if the last transmission was at least RETRANSMIT_WAIT seconds ago */ |
453 | + if (*now - HIP_RETRANSMIT_WAIT > retrans->last_transmit) { |
454 | + if (retrans->count > 0) { |
455 | + /* @todo: verify that this works over slow ADSL line */ |
456 | + if (hip_send_pkt(&retrans->saddr, |
457 | + &retrans->daddr, |
458 | + entry->nat_mode ? hip_get_local_nat_udp_port() : 0, |
459 | + entry->peer_udp_port, |
460 | + retrans->buf, |
461 | + entry, 0) == 0) { |
462 | + /* Set entry state, if previous state was unassociated |
463 | + * and type is I1. */ |
464 | + if (hip_get_msg_type(retrans->buf) == HIP_I1 && |
465 | + entry->state == HIP_STATE_UNASSOCIATED) { |
466 | + HIP_DEBUG("Resent I1 succcesfully\n"); |
467 | + entry->state = HIP_STATE_I1_SENT; |
468 | + } |
469 | + } else { |
470 | + HIP_ERROR("Failed to retransmit packet of type %d.\n", |
471 | + hip_get_msg_type(retrans->buf)); |
472 | + err = -1; |
473 | + } |
474 | + |
475 | + retrans->count--; |
476 | + time(&retrans->last_transmit); |
477 | + } else if (hip_get_msg_type(retrans->buf)) { |
478 | + hip_clear_retransmission(retrans); |
479 | } |
480 | } |
481 | } |
482 | |
483 | -out_err: |
484 | - |
485 | return err; |
486 | } |
487 | |
488 | @@ -151,7 +145,7 @@ |
489 | time_t current_time; |
490 | time(¤t_time); |
491 | |
492 | - if (hip_for_each_ha(handle_retransmission, ¤t_time)) { |
493 | + if (hip_for_each_ha(handle_retransmissions, ¤t_time)) { |
494 | return -1; |
495 | } |
496 | return 0; |
497 | |
498 | === modified file 'hipd/netdev.c' |
499 | --- hipd/netdev.c 2011-12-09 09:32:56 +0000 |
500 | +++ hipd/netdev.c 2011-12-29 15:06:25 +0000 |
501 | @@ -921,12 +921,15 @@ |
502 | |
503 | send_i1: |
504 | |
505 | - if (entry->hip_msg_retrans.count == 0) { |
506 | - HIP_DEBUG("Expired retransmissions, sending i1\n"); |
507 | - } else { |
508 | - HIP_DEBUG("I1 was already sent, ignoring\n"); |
509 | - goto out_err; |
510 | + HIP_DEBUG("Checking for older queued I1 transmissions.\n"); |
511 | + for (unsigned int i = 0; i < HIP_RETRANSMIT_QUEUE_SIZE; i++) { |
512 | + if (entry->hip_msg_retrans[i].count > 0 |
513 | + && hip_get_msg_type(entry->hip_msg_retrans[i].buf) == HIP_I1) { |
514 | + HIP_DEBUG("I1 was already sent, ignoring\n"); |
515 | + goto out_err; |
516 | + } |
517 | } |
518 | + HIP_DEBUG("Expired retransmissions, sending i1\n"); |
519 | |
520 | is_ipv4_locator = IN6_IS_ADDR_V4MAPPED(&entry->peer_addr); |
521 | |
522 | |
523 | === modified file 'hipd/output.c' |
524 | --- hipd/output.c 2011-11-10 10:53:21 +0000 |
525 | +++ hipd/output.c 2011-12-29 15:06:25 +0000 |
526 | @@ -1066,7 +1066,7 @@ |
527 | err = hip_send_pkt(&ctx->dst_addr, &ctx->src_addr, |
528 | ctx->hadb_entry->nat_mode ? hip_get_local_nat_udp_port() : 0, |
529 | ctx->hadb_entry->peer_udp_port, ctx->output_msg, |
530 | - ctx->hadb_entry, 1); |
531 | + ctx->hadb_entry, 0); |
532 | |
533 | HIP_IFEL(err, -ECOMM, "Sending R2 packet failed.\n"); |
534 | |
535 | @@ -1111,29 +1111,30 @@ |
536 | * destination HITs. |
537 | * @param entry a pointer to the current host association database state. |
538 | * @return zero |
539 | - * @note currently the queue length is one and new packets replace old ones |
540 | */ |
541 | static int queue_packet(const struct in6_addr *src_addr, |
542 | const struct in6_addr *peer_addr, |
543 | const struct hip_common *msg, |
544 | struct hip_hadb_state *entry) |
545 | { |
546 | - int len = hip_get_msg_total_len(msg); |
547 | + struct hip_msg_retrans *retrans; |
548 | |
549 | if (!entry) { |
550 | return 0; |
551 | } |
552 | |
553 | + retrans = &entry->hip_msg_retrans[entry->next_retrans_slot]; |
554 | + |
555 | /* Not reusing the old entry as the new packet may have different length */ |
556 | - memset(entry->hip_msg_retrans.buf, 0, HIP_MAX_NETWORK_PACKET); |
557 | - |
558 | - memcpy(entry->hip_msg_retrans.buf, msg, len); |
559 | - memcpy(&entry->hip_msg_retrans.saddr, src_addr, |
560 | - sizeof(struct in6_addr)); |
561 | - memcpy(&entry->hip_msg_retrans.daddr, peer_addr, |
562 | - sizeof(struct in6_addr)); |
563 | - entry->hip_msg_retrans.count = HIP_RETRANSMIT_MAX; |
564 | - time(&entry->hip_msg_retrans.last_transmit); |
565 | + memset(retrans->buf, 0, HIP_MAX_NETWORK_PACKET); |
566 | + |
567 | + memcpy(retrans->buf, msg, hip_get_msg_total_len(msg)); |
568 | + ipv6_addr_copy(&retrans->saddr, src_addr); |
569 | + ipv6_addr_copy(&retrans->daddr, peer_addr); |
570 | + retrans->count = HIP_RETRANSMIT_MAX; |
571 | + time(&retrans->last_transmit); |
572 | + |
573 | + entry->next_retrans_slot = (entry->next_retrans_slot + 1) % HIP_RETRANSMIT_QUEUE_SIZE; |
574 | |
575 | return 0; |
576 | } |
577 | |
578 | === modified file 'lib/core/state.h' |
579 | --- lib/core/state.h 2011-12-16 13:37:33 +0000 |
580 | +++ lib/core/state.h 2011-12-29 15:06:25 +0000 |
581 | @@ -100,6 +100,9 @@ |
582 | HIP_HA_STATE_VALID = 1, |
583 | }; |
584 | |
585 | +/* The maximum number of retransmissions to queue. */ |
586 | +#define HIP_RETRANSMIT_QUEUE_SIZE 3 |
587 | + |
588 | /** |
589 | * A data structure for handling retransmission. Used inside host association |
590 | * database entries. |
591 | @@ -157,9 +160,6 @@ |
592 | int purge_timeout; |
593 | /** The state of this host association. */ |
594 | enum hip_state state; |
595 | - /** This guarantees that retransmissions work properly also in |
596 | - * non-established state.*/ |
597 | - enum hip_state retrans_state; |
598 | /** Our control values related to this host association. |
599 | * @see hip_ha_controls */ |
600 | hip_controls local_controls; |
601 | @@ -282,8 +282,11 @@ |
602 | unsigned char echo_data[4]; |
603 | |
604 | HIP_HASHTABLE *peer_addr_list_to_be_added; |
605 | + /** The slot in our struct hip_msg_retrans array which will be used to save |
606 | + * the next retransmission. */ |
607 | + unsigned int next_retrans_slot; |
608 | /** For storing retransmission related data. */ |
609 | - struct hip_msg_retrans hip_msg_retrans; |
610 | + struct hip_msg_retrans hip_msg_retrans[HIP_RETRANSMIT_QUEUE_SIZE]; |
611 | /** peer hostname */ |
612 | uint8_t peer_hostname[HIP_HOST_ID_HOSTNAME_LEN_MAX]; |
613 | /** Counters of heartbeats (ICMPv6s) */ |
614 | |
615 | === modified file 'modules/update/hipd/update.c' |
616 | --- modules/update/hipd/update.c 2011-12-16 13:37:33 +0000 |
617 | +++ modules/update/hipd/update.c 2011-12-29 15:06:25 +0000 |
618 | @@ -364,7 +364,7 @@ |
619 | ctx->hadb_entry->peer_udp_port, |
620 | ctx->output_msg, |
621 | ctx->hadb_entry, |
622 | - 1); |
623 | + 0); |
624 | } |
625 | |
626 | return err; |
627 | @@ -810,6 +810,11 @@ |
628 | -1, "Error on registering UPDATE handle function.\n"); |
629 | HIP_IFEL(hip_register_handle_function(HIP_UPDATE, |
630 | HIP_STATE_R2_SENT, |
631 | + &hip_update_retransmissions, |
632 | + 20150), |
633 | + -1, "Error on registering UPDATE handle function.\n"); |
634 | + HIP_IFEL(hip_register_handle_function(HIP_UPDATE, |
635 | + HIP_STATE_R2_SENT, |
636 | &prepare_update_response, |
637 | 20200), |
638 | -1, "Error on registering UPDATE handle function.\n"); |
639 | @@ -896,6 +901,11 @@ |
640 | -1, "Error on registering UPDATE handle function.\n"); |
641 | HIP_IFEL(hip_register_handle_function(HIP_UPDATE, |
642 | HIP_STATE_ESTABLISHED, |
643 | + &hip_update_retransmissions, |
644 | + 20150), |
645 | + -1, "Error on registering UPDATE handle function.\n"); |
646 | + HIP_IFEL(hip_register_handle_function(HIP_UPDATE, |
647 | + HIP_STATE_ESTABLISHED, |
648 | &prepare_update_response, |
649 | 20200), |
650 | -1, "Error on registering UPDATE handle function.\n"); |
Seems good to me from the view point of functionality. May I ask few questions though:
1. Did you test that memory is deallocated (valgrind) - optional, but extra good karma if you do this :)
2. Does the scheme ignore retransmission of R1 messages (not really supposed to be resent)
3. Why to buffer to three messages?
Regarding to buffering, the state may change during retransmission and this causes the implementation to resend old messages in addition to new ones? If we're lucky, the peer will ignore UPDATE packets with old SPI numbers. However, the situation may be different in the BEX because there's no state.
A special (and supported) use case from base exchange: try to trigger the BEX simultaneously from both sides (i.e. break point both sides with gdb just after sending I1). I know the state machine can handle this but what happens to the retransmissions?