diff --git a/mongoose.c b/mongoose.c index 9602e79494..742551b870 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4511,9 +4511,20 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) { static void onstatechange(struct mg_tcpip_if *ifp) { if (ifp->state == MG_TCPIP_STATE_READY) { + struct mg_connection *c; MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip)); MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw)); MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac)); + for (c = ifp->mgr->conns; c != NULL; c = c->next) { + if (ifp->is_ip_changed) { + if (c->is_listening || c->is_udp) { + c->loc.ip4 = c->mgr->ifp->ip; + } else { + c->is_closing = 1; + } + } + } + ifp->is_ip_changed = false; } else if (ifp->state == MG_TCPIP_STATE_IP) { mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request } else if (ifp->state == MG_TCPIP_STATE_UP) { @@ -4800,6 +4811,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); // assume DHCP server = router until ARP resolves memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); + if (ifp->ip != ip) ifp->is_ip_changed = true; ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; ifp->state = MG_TCPIP_STATE_IP; // BOUND state mg_random(&rand, sizeof(rand)); @@ -5012,15 +5024,15 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len, uint8_t *mac) { uint8_t full = prefix_len / 8; uint8_t rem = prefix_len % 8; - if (full >= 8 && rem != 0) { + if (full > 8 || (full == 8 && rem != 0)) { MG_ERROR(("Prefix length > 64, UNSUPPORTED")); return false; } else if (full == 8 && rem == 0) { ip6gen((uint8_t *) ip6, prefix, mac); } else { ip6[0] = ip6[1] = 0; // already zeroed before firing RS... - if (full) memcpy(ip6, prefix, full); - if (rem) { + if (full > 0) memcpy(ip6, prefix, full); + if (rem > 0) { uint8_t mask = (uint8_t) (0xFF << (8 - rem)); ((uint8_t *) ip6)[full] = prefix[full] & mask; } @@ -5029,6 +5041,27 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len, return true; } +static bool match_prefix(uint8_t *new, uint8_t len, uint8_t *cur, + uint8_t *cur_len) { + uint8_t full = len / 8; + uint8_t rem = len % 8; + bool res = true; + if (full > 8 || (full == 8 && rem != 0)) + return false; // Prefix length > 64: UNSUPPORTED + if (*cur_len != len) res = false; + if (full > 0) { + if (res && memcmp(cur, new, full) != 0) res = false; + memcpy(cur, new, full); + } + if (rem > 0) { + uint8_t mask = (uint8_t) (0xFF << (8 - rem)); + if (res && cur[full] != (new[full] & mask)) res = false; + cur[full] = new[full] & mask; + } + *cur_len = len; + return res; +} + // Router Advertisement, 4.2 static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) { if (pkt->pay.len < 12) return; @@ -5063,14 +5096,13 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) { uint8_t *prefix = opts + 16; // TODO (robertc2000): handle prefix options if necessary - (void) prefix_len; (void) pfx_flags; (void) valid; (void) pref_lifetime; - (void) prefix; - // fill prefix length and global - ifp->prefix_len = prefix_len; + // fill prefix and global address + if (!match_prefix(prefix, prefix_len, ifp->prefix, &ifp->prefix_len)) + ifp->is_ip6_changed = true; if (!fill_global(ifp->ip6, prefix, prefix_len, ifp->mac)) return; } opts += length; @@ -5113,10 +5145,21 @@ static void rx_icmp6(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void onstate6change(struct mg_tcpip_if *ifp) { + struct mg_connection *c; if (ifp->state6 == MG_TCPIP_STATE_READY) { MG_INFO(("READY, IP: %M", mg_print_ip6, &ifp->ip6)); MG_INFO((" GW: %M", mg_print_ip6, &ifp->gw6)); MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac)); + for (c = ifp->mgr->conns; c != NULL; c = c->next) { + if (ifp->is_ip6_changed) { + if (c->is_listening || c->is_udp) { + c->loc.ip6[0] = ifp->ip6[0], c->loc.ip6[1] = ifp->ip6[1]; + } else { + c->is_closing = 1; + } + } + } + ifp->is_ip6_changed = false; } else if (ifp->state6 == MG_TCPIP_STATE_IP) { tx_ndp_ns(ifp, ifp->gw6, ifp->gw6mac); // unsolicited GW MAC resolution } else if (ifp->state6 == MG_TCPIP_STATE_UP) { @@ -5603,10 +5646,10 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) { if (ihl < 5) return; // bad IHL if (pkt->pay.len < (uint16_t) (ihl * 4)) return; // Truncated / malformed // There can be link padding, take length from IP header - len = mg_ntohs(pkt->ip->len); // IP datagram length + len = mg_ntohs(pkt->ip->len); // IP datagram length if (len < (uint16_t) (ihl * 4) || len > pkt->pay.len) return; // malformed - pkt->pay.len = len; // strip padding - mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts + pkt->pay.len = len; // strip padding + mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts frag = mg_ntohs(pkt->ip->frag); if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) { struct mg_connection *c; @@ -25213,15 +25256,11 @@ enum { EPHYSTS = 16 }; // PHY constants -static inline void tm4cspin(volatile uint32_t count) { - while (count--) (void) 0; -} - static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) { EMAC->EMACMIIADDR &= (0xf << 2); EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6); EMAC->EMACMIIADDR |= MG_BIT(0); - while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1); + while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0; return EMAC->EMACMIIDATA; } @@ -25231,7 +25270,7 @@ static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) { EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1); EMAC->EMACMIIADDR |= MG_BIT(0); - while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1); + while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0; } static uint32_t get_sysclk(void) { @@ -25323,9 +25362,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) { (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain } - EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset - while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) - tm4cspin(1); // Wait until done + EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset + while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) (void) 0; // Wait until done // Set MDC clock divider. If user told us the value, use it. Otherwise, guess int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr; diff --git a/mongoose.h b/mongoose.h index 5592d83dbe..91ba8a38f3 100644 --- a/mongoose.h +++ b/mongoose.h @@ -3135,17 +3135,20 @@ typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev, void *ev_data); enum { - MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state) - MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr - MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr - MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str * - MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL - MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct mg_wifi_scan_bss_data * - MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL - MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and chip specific - MG_TCPIP_EV_DRIVER, // Driver event driver specific - MG_TCPIP_EV_ST6_CHG, // state6 change uint8_t * (&ifp->state6) - MG_TCPIP_EV_USER // Starting ID for user events + MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state) + MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr + MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr + MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str * + MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL + MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct + // mg_wifi_scan_bss_data * + MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL + MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and + // chip specific + MG_TCPIP_EV_DRIVER, // Driver event driver specific + MG_TCPIP_EV_ST6_CHG, // state6 change uint8_t * + // (&ifp->state6) + MG_TCPIP_EV_USER // Starting ID for user events }; // Network interface @@ -3161,6 +3164,7 @@ struct mg_tcpip_if { bool enable_crc32_check; // Do a CRC check on RX frames and strip it bool enable_mac_check; // Do a MAC check on RX frames bool update_mac_hash_table; // Signal drivers to update MAC controller + bool is_ip_changed; // IP address changed, close/restart conns struct mg_tcpip_driver *driver; // Low level driver void *driver_data; // Driver-specific data mg_tcpip_event_handler_t pfn; // Driver-specific event handler function @@ -3171,11 +3175,13 @@ struct mg_tcpip_if { uint16_t mtu; // Interface MTU #define MG_TCPIP_MTU_DEFAULT 1500 #if MG_ENABLE_IPV6 - uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses - uint8_t prefix_len; // Prefix length - uint64_t gw6[2]; // Default gateway - bool enable_slaac; // Enable IPv6 address autoconfiguration - bool enable_dhcp6_client; // Enable DCHPv6 client + uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses + uint8_t prefix[8]; // IPv6 global address prefix + uint8_t prefix_len; // Prefix length + uint64_t gw6[2]; // Default gateway + bool enable_slaac; // Enable IPv6 address autoconfiguration + bool enable_dhcp6_client; // Enable DCHPv6 client + bool is_ip6_changed; // IPv6 address changed, close/restart conns #endif // Internal state, user can use it but should not change it @@ -3196,8 +3202,8 @@ struct mg_tcpip_if { #define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned #define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work #if MG_ENABLE_IPV6 - uint8_t gw6mac[6]; // IPv6 Router's MAC - uint8_t state6; // Current IPv6 state + uint8_t gw6mac[6]; // IPv6 Router's MAC + uint8_t state6; // Current IPv6 state #endif }; void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); @@ -3231,39 +3237,38 @@ struct mg_tcpip_spi { uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply }; - // Alignment and memory section requirements #ifndef MG_8BYTE_ALIGNED #if defined(__GNUC__) #define MG_8BYTE_ALIGNED __attribute__((aligned((8U)))) #else #define MG_8BYTE_ALIGNED -#endif // compiler -#endif // 8BYTE_ALIGNED +#endif // compiler +#endif // 8BYTE_ALIGNED #ifndef MG_16BYTE_ALIGNED #if defined(__GNUC__) #define MG_16BYTE_ALIGNED __attribute__((aligned((16U)))) #else #define MG_16BYTE_ALIGNED -#endif // compiler -#endif // 16BYTE_ALIGNED +#endif // compiler +#endif // 16BYTE_ALIGNED #ifndef MG_32BYTE_ALIGNED #if defined(__GNUC__) #define MG_32BYTE_ALIGNED __attribute__((aligned((32U)))) #else #define MG_32BYTE_ALIGNED -#endif // compiler -#endif // 32BYTE_ALIGNED +#endif // compiler +#endif // 32BYTE_ALIGNED #ifndef MG_64BYTE_ALIGNED #if defined(__GNUC__) #define MG_64BYTE_ALIGNED __attribute__((aligned((64U)))) #else #define MG_64BYTE_ALIGNED -#endif // compiler -#endif // 64BYTE_ALIGNED +#endif // compiler +#endif // 64BYTE_ALIGNED #ifndef MG_ETH_RAM #define MG_ETH_RAM diff --git a/src/drivers/tm4c.c b/src/drivers/tm4c.c index 31efafad4a..a7adb1a474 100644 --- a/src/drivers/tm4c.c +++ b/src/drivers/tm4c.c @@ -40,15 +40,11 @@ enum { EPHYSTS = 16 }; // PHY constants -static inline void tm4cspin(volatile uint32_t count) { - while (count--) (void) 0; -} - static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) { EMAC->EMACMIIADDR &= (0xf << 2); EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6); EMAC->EMACMIIADDR |= MG_BIT(0); - while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1); + while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0; return EMAC->EMACMIIDATA; } @@ -58,7 +54,7 @@ static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) { EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1); EMAC->EMACMIIADDR |= MG_BIT(0); - while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1); + while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0; } static uint32_t get_sysclk(void) { @@ -150,9 +146,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) { (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain } - EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset - while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) - tm4cspin(1); // Wait until done + EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset + while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) (void) 0; // Wait until done // Set MDC clock divider. If user told us the value, use it. Otherwise, guess int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr; diff --git a/src/net_builtin.c b/src/net_builtin.c index 29a1f6b1aa..ff842d9f7c 100644 --- a/src/net_builtin.c +++ b/src/net_builtin.c @@ -305,9 +305,20 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) { static void onstatechange(struct mg_tcpip_if *ifp) { if (ifp->state == MG_TCPIP_STATE_READY) { + struct mg_connection *c; MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip)); MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw)); MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac)); + for (c = ifp->mgr->conns; c != NULL; c = c->next) { + if (ifp->is_ip_changed) { + if (c->is_listening || c->is_udp) { + c->loc.ip4 = c->mgr->ifp->ip; + } else { + c->is_closing = 1; + } + } + } + ifp->is_ip_changed = false; } else if (ifp->state == MG_TCPIP_STATE_IP) { mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request } else if (ifp->state == MG_TCPIP_STATE_UP) { @@ -594,6 +605,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) { MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000)); // assume DHCP server = router until ARP resolves memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac)); + if (ifp->ip != ip) ifp->is_ip_changed = true; ifp->ip = ip, ifp->gw = gw, ifp->mask = mask; ifp->state = MG_TCPIP_STATE_IP; // BOUND state mg_random(&rand, sizeof(rand)); @@ -806,15 +818,15 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len, uint8_t *mac) { uint8_t full = prefix_len / 8; uint8_t rem = prefix_len % 8; - if (full >= 8 && rem != 0) { + if (full > 8 || (full == 8 && rem != 0)) { MG_ERROR(("Prefix length > 64, UNSUPPORTED")); return false; } else if (full == 8 && rem == 0) { ip6gen((uint8_t *) ip6, prefix, mac); } else { ip6[0] = ip6[1] = 0; // already zeroed before firing RS... - if (full) memcpy(ip6, prefix, full); - if (rem) { + if (full > 0) memcpy(ip6, prefix, full); + if (rem > 0) { uint8_t mask = (uint8_t) (0xFF << (8 - rem)); ((uint8_t *) ip6)[full] = prefix[full] & mask; } @@ -823,6 +835,27 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len, return true; } +static bool match_prefix(uint8_t *new, uint8_t len, uint8_t *cur, + uint8_t *cur_len) { + uint8_t full = len / 8; + uint8_t rem = len % 8; + bool res = true; + if (full > 8 || (full == 8 && rem != 0)) + return false; // Prefix length > 64: UNSUPPORTED + if (*cur_len != len) res = false; + if (full > 0) { + if (res && memcmp(cur, new, full) != 0) res = false; + memcpy(cur, new, full); + } + if (rem > 0) { + uint8_t mask = (uint8_t) (0xFF << (8 - rem)); + if (res && cur[full] != (new[full] & mask)) res = false; + cur[full] = new[full] & mask; + } + *cur_len = len; + return res; +} + // Router Advertisement, 4.2 static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) { if (pkt->pay.len < 12) return; @@ -857,14 +890,13 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) { uint8_t *prefix = opts + 16; // TODO (robertc2000): handle prefix options if necessary - (void) prefix_len; (void) pfx_flags; (void) valid; (void) pref_lifetime; - (void) prefix; - // fill prefix length and global - ifp->prefix_len = prefix_len; + // fill prefix and global address + if (!match_prefix(prefix, prefix_len, ifp->prefix, &ifp->prefix_len)) + ifp->is_ip6_changed = true; if (!fill_global(ifp->ip6, prefix, prefix_len, ifp->mac)) return; } opts += length; @@ -907,10 +939,21 @@ static void rx_icmp6(struct mg_tcpip_if *ifp, struct pkt *pkt) { } static void onstate6change(struct mg_tcpip_if *ifp) { + struct mg_connection *c; if (ifp->state6 == MG_TCPIP_STATE_READY) { MG_INFO(("READY, IP: %M", mg_print_ip6, &ifp->ip6)); MG_INFO((" GW: %M", mg_print_ip6, &ifp->gw6)); MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac)); + for (c = ifp->mgr->conns; c != NULL; c = c->next) { + if (ifp->is_ip6_changed) { + if (c->is_listening || c->is_udp) { + c->loc.ip6[0] = ifp->ip6[0], c->loc.ip6[1] = ifp->ip6[1]; + } else { + c->is_closing = 1; + } + } + } + ifp->is_ip6_changed = false; } else if (ifp->state6 == MG_TCPIP_STATE_IP) { tx_ndp_ns(ifp, ifp->gw6, ifp->gw6mac); // unsolicited GW MAC resolution } else if (ifp->state6 == MG_TCPIP_STATE_UP) { @@ -1397,10 +1440,10 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) { if (ihl < 5) return; // bad IHL if (pkt->pay.len < (uint16_t) (ihl * 4)) return; // Truncated / malformed // There can be link padding, take length from IP header - len = mg_ntohs(pkt->ip->len); // IP datagram length + len = mg_ntohs(pkt->ip->len); // IP datagram length if (len < (uint16_t) (ihl * 4) || len > pkt->pay.len) return; // malformed - pkt->pay.len = len; // strip padding - mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts + pkt->pay.len = len; // strip padding + mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts frag = mg_ntohs(pkt->ip->frag); if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) { struct mg_connection *c; diff --git a/src/net_builtin.h b/src/net_builtin.h index ec88f51c59..b762e875cf 100644 --- a/src/net_builtin.h +++ b/src/net_builtin.h @@ -20,17 +20,20 @@ typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev, void *ev_data); enum { - MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state) - MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr - MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr - MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str * - MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL - MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct mg_wifi_scan_bss_data * - MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL - MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and chip specific - MG_TCPIP_EV_DRIVER, // Driver event driver specific - MG_TCPIP_EV_ST6_CHG, // state6 change uint8_t * (&ifp->state6) - MG_TCPIP_EV_USER // Starting ID for user events + MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state) + MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr + MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr + MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str * + MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL + MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct + // mg_wifi_scan_bss_data * + MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL + MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and + // chip specific + MG_TCPIP_EV_DRIVER, // Driver event driver specific + MG_TCPIP_EV_ST6_CHG, // state6 change uint8_t * + // (&ifp->state6) + MG_TCPIP_EV_USER // Starting ID for user events }; // Network interface @@ -46,6 +49,7 @@ struct mg_tcpip_if { bool enable_crc32_check; // Do a CRC check on RX frames and strip it bool enable_mac_check; // Do a MAC check on RX frames bool update_mac_hash_table; // Signal drivers to update MAC controller + bool is_ip_changed; // IP address changed, close/restart conns struct mg_tcpip_driver *driver; // Low level driver void *driver_data; // Driver-specific data mg_tcpip_event_handler_t pfn; // Driver-specific event handler function @@ -56,11 +60,13 @@ struct mg_tcpip_if { uint16_t mtu; // Interface MTU #define MG_TCPIP_MTU_DEFAULT 1500 #if MG_ENABLE_IPV6 - uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses - uint8_t prefix_len; // Prefix length - uint64_t gw6[2]; // Default gateway - bool enable_slaac; // Enable IPv6 address autoconfiguration - bool enable_dhcp6_client; // Enable DCHPv6 client + uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses + uint8_t prefix[8]; // IPv6 global address prefix + uint8_t prefix_len; // Prefix length + uint64_t gw6[2]; // Default gateway + bool enable_slaac; // Enable IPv6 address autoconfiguration + bool enable_dhcp6_client; // Enable DCHPv6 client + bool is_ip6_changed; // IPv6 address changed, close/restart conns #endif // Internal state, user can use it but should not change it @@ -81,8 +87,8 @@ struct mg_tcpip_if { #define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned #define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work #if MG_ENABLE_IPV6 - uint8_t gw6mac[6]; // IPv6 Router's MAC - uint8_t state6; // Current IPv6 state + uint8_t gw6mac[6]; // IPv6 Router's MAC + uint8_t state6; // Current IPv6 state #endif }; void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *); @@ -116,39 +122,38 @@ struct mg_tcpip_spi { uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply }; - // Alignment and memory section requirements #ifndef MG_8BYTE_ALIGNED #if defined(__GNUC__) #define MG_8BYTE_ALIGNED __attribute__((aligned((8U)))) #else #define MG_8BYTE_ALIGNED -#endif // compiler -#endif // 8BYTE_ALIGNED +#endif // compiler +#endif // 8BYTE_ALIGNED #ifndef MG_16BYTE_ALIGNED #if defined(__GNUC__) #define MG_16BYTE_ALIGNED __attribute__((aligned((16U)))) #else #define MG_16BYTE_ALIGNED -#endif // compiler -#endif // 16BYTE_ALIGNED +#endif // compiler +#endif // 16BYTE_ALIGNED #ifndef MG_32BYTE_ALIGNED #if defined(__GNUC__) #define MG_32BYTE_ALIGNED __attribute__((aligned((32U)))) #else #define MG_32BYTE_ALIGNED -#endif // compiler -#endif // 32BYTE_ALIGNED +#endif // compiler +#endif // 32BYTE_ALIGNED #ifndef MG_64BYTE_ALIGNED #if defined(__GNUC__) #define MG_64BYTE_ALIGNED __attribute__((aligned((64U)))) #else #define MG_64BYTE_ALIGNED -#endif // compiler -#endif // 64BYTE_ALIGNED +#endif // compiler +#endif // 64BYTE_ALIGNED #ifndef MG_ETH_RAM #define MG_ETH_RAM diff --git a/test/mip_test.c b/test/mip_test.c index 7097b1d1b2..e260299ba1 100644 --- a/test/mip_test.c +++ b/test/mip_test.c @@ -56,12 +56,14 @@ static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) { } static void test_statechange(void) { + struct mg_mgr mgr; struct mg_tcpip_if iface; memset(&iface, 0, sizeof(iface)); iface.ip = mg_htonl(0x01020304); iface.state = MG_TCPIP_STATE_READY; iface.driver = &mg_tcpip_driver_mock; iface.fn = mif_fn; + iface.mgr = &mgr; onstatechange(&iface); ASSERT(executed == true); executed = false; @@ -76,6 +78,7 @@ static void mif6_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) { } static void test_state6change(void) { + struct mg_mgr mgr; struct mg_tcpip_if iface; memset(&iface, 0, sizeof(iface)); iface.ip6[0] = (uint64_t) mg_htonl(0x01020304); @@ -83,6 +86,7 @@ static void test_state6change(void) { iface.state6 = MG_TCPIP_STATE_READY; iface.driver = &mg_tcpip_driver_mock; iface.fn = mif6_fn; + iface.mgr = &mgr; onstate6change(&iface); ASSERT(executed == true); executed = false;