67#if LWIP_IPV4 && LWIP_ACD
74#define ACD_FOREACH(acd, acd_list) for ((acd) = acd_list; (acd) != NULL; (acd) = (acd)->next)
76#define ACD_TICKS_PER_SECOND (1000 / ACD_TMR_INTERVAL)
80#define LWIP_ACD_RAND(netif, acd) LWIP_RAND()
82#ifdef LWIP_AUTOIP_RAND
84#define LWIP_ACD_RAND(netif, acd) LWIP_AUTOIP_RAND(netif)
86#define LWIP_ACD_RAND(netif, acd) ((((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
87 ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
88 ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
89 ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
95#define ACD_RANDOM_PROBE_WAIT(netif, acd) (LWIP_ACD_RAND(netif, acd) % \
96 (PROBE_WAIT * ACD_TICKS_PER_SECOND))
98#define ACD_RANDOM_PROBE_INTERVAL(netif, acd) ((LWIP_ACD_RAND(netif, acd) % \
99 ((PROBE_MAX - PROBE_MIN) * ACD_TICKS_PER_SECOND)) + \
100 (PROBE_MIN * ACD_TICKS_PER_SECOND ))
103static void acd_restart(
struct netif *
netif,
struct acd *acd);
104static void acd_handle_arp_conflict(
struct netif *
netif,
struct acd *acd);
105static void acd_put_in_passive_mode(
struct netif *
netif,
struct acd *acd);
119 acd_conflict_callback_t acd_conflict_callback)
125 LWIP_ASSERT(
"acd_conflict_callback != NULL", acd_conflict_callback != NULL);
126 acd->acd_conflict_callback = acd_conflict_callback;
129 for (acd2 =
netif->acd_list; acd2 != NULL; acd2 = acd2->
next) {
132 (
"acd_add(): acd already added to list\n"));
138 acd->next =
netif->acd_list;
139 netif->acd_list = acd;
152acd_remove(
struct netif *
netif,
struct acd *acd)
154 struct acd *acd2, *prev = NULL;
158 for (acd2 =
netif->acd_list; acd2 != NULL; acd2 = acd2->
next) {
161 prev->next = acd->next;
169 LWIP_ASSERT((
"acd_remove(): acd not on list\n"), 0);
188 (
"acd_start(netif=%p) %c%c%"U16_F
"\n",
194 acd->lastconflict = 0;
196 acd->state = ACD_STATE_PROBE_WAIT;
198 acd->ttw = (u16_t)(ACD_RANDOM_PROBE_WAIT(
netif, acd));
210acd_stop(
struct acd *acd)
215 acd->state = ACD_STATE_OFF;
227acd_network_changed_link_down(
struct netif *
netif)
231 ACD_FOREACH(acd,
netif->acd_list) {
245 NETIF_FOREACH(
netif) {
246 ACD_FOREACH(acd,
netif->acd_list) {
247 if (acd->lastconflict > 0) {
252 (
"acd_tmr() ACD-State: %"U16_F
", ttw=%"U16_F
"\n",
253 (u16_t)(acd->state), acd->ttw));
259 switch (acd->state) {
260 case ACD_STATE_PROBE_WAIT:
261 case ACD_STATE_PROBING:
263 acd->state = ACD_STATE_PROBING;
264 etharp_acd_probe(
netif, &acd->ipaddr);
266 (
"acd_tmr() PROBING Sent Probe\n"));
268 if (acd->sent_num >= PROBE_NUM) {
270 acd->state = ACD_STATE_ANNOUNCE_WAIT;
275 acd->ttw = (u16_t)(ANNOUNCE_WAIT * ACD_TICKS_PER_SECOND);
278 acd->ttw = (u16_t)(ACD_RANDOM_PROBE_INTERVAL(
netif, acd));
283 case ACD_STATE_ANNOUNCE_WAIT:
284 case ACD_STATE_ANNOUNCING:
286 if (acd->sent_num == 0) {
287 acd->state = ACD_STATE_ANNOUNCING;
290 acd->num_conflicts = 0;
293 (
"acd_tmr(): changing state to ANNOUNCING: %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
"\n",
294 ip4_addr1_16(&acd->ipaddr), ip4_addr2_16(&acd->ipaddr),
295 ip4_addr3_16(&acd->ipaddr), ip4_addr4_16(&acd->ipaddr)));
298 etharp_acd_announce(
netif, &acd->ipaddr);
300 (
"acd_tmr() ANNOUNCING Sent Announce\n"));
301 acd->ttw = ANNOUNCE_INTERVAL * ACD_TICKS_PER_SECOND;
304 if (acd->sent_num >= ANNOUNCE_NUM) {
305 acd->state = ACD_STATE_ONGOING;
309 (
"acd_tmr(): changing state to ONGOING: %"U16_F
".%"U16_F
".%"U16_F
".%"U16_F
"\n",
310 ip4_addr1_16(&acd->ipaddr), ip4_addr2_16(&acd->ipaddr),
311 ip4_addr3_16(&acd->ipaddr), ip4_addr4_16(&acd->ipaddr)));
314 acd->acd_conflict_callback(
netif, ACD_IP_OK);
319 case ACD_STATE_RATE_LIMIT:
326 acd->acd_conflict_callback(
netif, ACD_RESTART_CLIENT);
344acd_restart(
struct netif *
netif,
struct acd *acd)
347 acd->num_conflicts++;
350 acd->acd_conflict_callback(
netif, ACD_DECLINE);
354 if (acd->num_conflicts >= MAX_CONFLICTS) {
355 acd->state = ACD_STATE_RATE_LIMIT;
356 acd->ttw = (u16_t)(RATE_LIMIT_INTERVAL * ACD_TICKS_PER_SECOND);
358 (
"acd_restart(): rate limiting initiated. too many conflicts\n"));
365 acd->acd_conflict_callback(
netif, ACD_RESTART_CLIENT);
393 ACD_FOREACH(acd,
netif->acd_list) {
396 case ACD_STATE_RATE_LIMIT:
401 case ACD_STATE_PROBE_WAIT:
402 case ACD_STATE_PROBING:
403 case ACD_STATE_ANNOUNCE_WAIT:
410 if ((ip4_addr_eq(&sipaddr, &acd->ipaddr)) ||
411 (ip4_addr_isany_val(sipaddr) &&
412 ip4_addr_eq(&dipaddr, &acd->ipaddr) &&
413 !eth_addr_eq(&netifaddr, &hdr->shwaddr))) {
415 (
"acd_arp_reply(): Probe Conflict detected\n"));
416 acd_restart(
netif, acd);
420 case ACD_STATE_ANNOUNCING:
421 case ACD_STATE_ONGOING:
422 case ACD_STATE_PASSIVE_ONGOING:
427 if (ip4_addr_eq(&sipaddr, &acd->ipaddr) &&
428 !eth_addr_eq(&netifaddr, &hdr->shwaddr)) {
430 (
"acd_arp_reply(): Conflicting ARP-Packet detected\n"));
431 acd_handle_arp_conflict(
netif, acd);
442acd_handle_arp_conflict(
struct netif *
netif,
struct acd *acd)
461 if (acd->state == ACD_STATE_PASSIVE_ONGOING) {
464 (
"acd_handle_arp_conflict(): conflict when we are in passive mode -> back off\n"));
466 acd->acd_conflict_callback(
netif, ACD_DECLINE);
469 if (acd->lastconflict > 0) {
472 (
"acd_handle_arp_conflict(): conflict within DEFEND_INTERVAL -> retreating\n"));
476 acd_restart(
netif, acd);
479 (
"acd_handle_arp_conflict(): we are defending, send ARP Announce\n"));
480 etharp_acd_announce(
netif, &acd->ipaddr);
481 acd->lastconflict = DEFEND_INTERVAL * ACD_TICKS_PER_SECOND;
490acd_put_in_passive_mode(
struct netif *
netif,
struct acd *acd)
494 case ACD_STATE_PASSIVE_ONGOING:
499 case ACD_STATE_PROBE_WAIT:
500 case ACD_STATE_PROBING:
501 case ACD_STATE_ANNOUNCE_WAIT:
502 case ACD_STATE_RATE_LIMIT:
504 acd->acd_conflict_callback(
netif, ACD_DECLINE);
507 case ACD_STATE_ANNOUNCING:
508 case ACD_STATE_ONGOING:
509 acd->state = ACD_STATE_PASSIVE_ONGOING;
511 (
"acd_put_in_passive_mode()\n"));
525acd_netif_ip_addr_changed(
struct netif *
netif,
const ip_addr_t *old_addr,
526 const ip_addr_t *new_addr)
531 (
"acd_netif_ip_addr_changed(): Address changed\n"));
534 (
"acd_netif_ip_addr_changed(): old address = %s\n", ipaddr_ntoa(old_addr)));
536 (
"acd_netif_ip_addr_changed(): new address = %s\n", ipaddr_ntoa(new_addr)));
539 if (ip_addr_isany(old_addr) || ip_addr_isany(new_addr)) {
543 ACD_FOREACH(acd,
netif->acd_list) {
545 if(ip4_addr_eq(&acd->ipaddr, ip_2_ip4(old_addr))) {
547 if (ip_addr_islinklocal(old_addr) && !ip_addr_islinklocal(new_addr)) {
549 (
"acd_netif_ip_addr_changed(): changed from LL to routable address\n"));
551 acd_put_in_passive_mode(
netif, acd);
#define ip4_addr_copy(dest, src)
#define LWIP_UNUSED_ARG(x)
#define LWIP_DBG_LEVEL_WARNING
#define LWIP_ASSERT_CORE_LOCKED()
#define SMEMCPY(dst, src, len)
#define IPADDR_WORDALIGNED_COPY_TO_IP4_ADDR_T(dest, src)
struct ip4_addr ip4_addr_t
u8 hwaddr[NETIF_MAX_HWADDR_LEN]