Skip to content

Commit 1043222

Browse files
cpqscaprile
authored andcommitted
Allow listeners to start before we have an address, close outstanding
TCP connections on address change
1 parent cac4b3e commit 1043222

File tree

6 files changed

+182
-92
lines changed

6 files changed

+182
-92
lines changed

mongoose.c

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4511,9 +4511,20 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) {
45114511

45124512
static void onstatechange(struct mg_tcpip_if *ifp) {
45134513
if (ifp->state == MG_TCPIP_STATE_READY) {
4514+
struct mg_connection *c;
45144515
MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
45154516
MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
45164517
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
4518+
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
4519+
if (ifp->is_ip_changed) {
4520+
if (c->is_listening || c->is_udp) {
4521+
c->loc.ip4 = c->mgr->ifp->ip;
4522+
} else {
4523+
c->is_closing = 1;
4524+
}
4525+
}
4526+
}
4527+
ifp->is_ip_changed = false;
45174528
} else if (ifp->state == MG_TCPIP_STATE_IP) {
45184529
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
45194530
} 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) {
48004811
MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
48014812
// assume DHCP server = router until ARP resolves
48024813
memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
4814+
if (ifp->ip != ip) ifp->is_ip_changed = true;
48034815
ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
48044816
ifp->state = MG_TCPIP_STATE_IP; // BOUND state
48054817
mg_random(&rand, sizeof(rand));
@@ -5012,15 +5024,15 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len,
50125024
uint8_t *mac) {
50135025
uint8_t full = prefix_len / 8;
50145026
uint8_t rem = prefix_len % 8;
5015-
if (full >= 8 && rem != 0) {
5027+
if (full > 8 || (full == 8 && rem != 0)) {
50165028
MG_ERROR(("Prefix length > 64, UNSUPPORTED"));
50175029
return false;
50185030
} else if (full == 8 && rem == 0) {
50195031
ip6gen((uint8_t *) ip6, prefix, mac);
50205032
} else {
50215033
ip6[0] = ip6[1] = 0; // already zeroed before firing RS...
5022-
if (full) memcpy(ip6, prefix, full);
5023-
if (rem) {
5034+
if (full > 0) memcpy(ip6, prefix, full);
5035+
if (rem > 0) {
50245036
uint8_t mask = (uint8_t) (0xFF << (8 - rem));
50255037
((uint8_t *) ip6)[full] = prefix[full] & mask;
50265038
}
@@ -5029,6 +5041,27 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len,
50295041
return true;
50305042
}
50315043

5044+
static bool match_prefix(uint8_t *new, uint8_t len, uint8_t *cur,
5045+
uint8_t *cur_len) {
5046+
uint8_t full = len / 8;
5047+
uint8_t rem = len % 8;
5048+
bool res = true;
5049+
if (full > 8 || (full == 8 && rem != 0))
5050+
return false; // Prefix length > 64: UNSUPPORTED
5051+
if (*cur_len != len) res = false;
5052+
if (full > 0) {
5053+
if (res && memcmp(cur, new, full) != 0) res = false;
5054+
memcpy(cur, new, full);
5055+
}
5056+
if (rem > 0) {
5057+
uint8_t mask = (uint8_t) (0xFF << (8 - rem));
5058+
if (res && cur[full] != (new[full] & mask)) res = false;
5059+
cur[full] = new[full] & mask;
5060+
}
5061+
*cur_len = len;
5062+
return res;
5063+
}
5064+
50325065
// Router Advertisement, 4.2
50335066
static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
50345067
if (pkt->pay.len < 12) return;
@@ -5063,14 +5096,13 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
50635096
uint8_t *prefix = opts + 16;
50645097

50655098
// TODO (robertc2000): handle prefix options if necessary
5066-
(void) prefix_len;
50675099
(void) pfx_flags;
50685100
(void) valid;
50695101
(void) pref_lifetime;
5070-
(void) prefix;
50715102

5072-
// fill prefix length and global
5073-
ifp->prefix_len = prefix_len;
5103+
// fill prefix and global address
5104+
if (!match_prefix(prefix, prefix_len, ifp->prefix, &ifp->prefix_len))
5105+
ifp->is_ip6_changed = true;
50745106
if (!fill_global(ifp->ip6, prefix, prefix_len, ifp->mac)) return;
50755107
}
50765108
opts += length;
@@ -5113,10 +5145,21 @@ static void rx_icmp6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
51135145
}
51145146

51155147
static void onstate6change(struct mg_tcpip_if *ifp) {
5148+
struct mg_connection *c;
51165149
if (ifp->state6 == MG_TCPIP_STATE_READY) {
51175150
MG_INFO(("READY, IP: %M", mg_print_ip6, &ifp->ip6));
51185151
MG_INFO((" GW: %M", mg_print_ip6, &ifp->gw6));
51195152
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
5153+
for (c = ifp->mgr->conns; c != NULL; c = c->next) {
5154+
if (ifp->is_ip6_changed) {
5155+
if (c->is_listening || c->is_udp) {
5156+
c->loc.ip6[0] = ifp->ip6[0], c->loc.ip6[1] = ifp->ip6[1];
5157+
} else {
5158+
c->is_closing = 1;
5159+
}
5160+
}
5161+
}
5162+
ifp->is_ip6_changed = false;
51205163
} else if (ifp->state6 == MG_TCPIP_STATE_IP) {
51215164
tx_ndp_ns(ifp, ifp->gw6, ifp->gw6mac); // unsolicited GW MAC resolution
51225165
} else if (ifp->state6 == MG_TCPIP_STATE_UP) {
@@ -5603,10 +5646,10 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
56035646
if (ihl < 5) return; // bad IHL
56045647
if (pkt->pay.len < (uint16_t) (ihl * 4)) return; // Truncated / malformed
56055648
// There can be link padding, take length from IP header
5606-
len = mg_ntohs(pkt->ip->len); // IP datagram length
5649+
len = mg_ntohs(pkt->ip->len); // IP datagram length
56075650
if (len < (uint16_t) (ihl * 4) || len > pkt->pay.len) return; // malformed
5608-
pkt->pay.len = len; // strip padding
5609-
mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts
5651+
pkt->pay.len = len; // strip padding
5652+
mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts
56105653
frag = mg_ntohs(pkt->ip->frag);
56115654
if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
56125655
struct mg_connection *c;
@@ -25213,15 +25256,11 @@ enum {
2521325256
EPHYSTS = 16
2521425257
}; // PHY constants
2521525258

25216-
static inline void tm4cspin(volatile uint32_t count) {
25217-
while (count--) (void) 0;
25218-
}
25219-
2522025259
static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
2522125260
EMAC->EMACMIIADDR &= (0xf << 2);
2522225261
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
2522325262
EMAC->EMACMIIADDR |= MG_BIT(0);
25224-
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
25263+
while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0;
2522525264
return EMAC->EMACMIIDATA;
2522625265
}
2522725266

@@ -25231,7 +25270,7 @@ static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
2523125270
EMAC->EMACMIIADDR |=
2523225271
((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
2523325272
EMAC->EMACMIIADDR |= MG_BIT(0);
25234-
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
25273+
while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0;
2523525274
}
2523625275

2523725276
static uint32_t get_sysclk(void) {
@@ -25323,9 +25362,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
2532325362
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
2532425363
}
2532525364

25326-
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
25327-
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0)
25328-
tm4cspin(1); // Wait until done
25365+
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
25366+
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) (void) 0; // Wait until done
2532925367

2533025368
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
2533125369
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;

mongoose.h

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3135,17 +3135,20 @@ typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev,
31353135
void *ev_data);
31363136

31373137
enum {
3138-
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
3139-
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
3140-
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
3141-
MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
3142-
MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
3143-
MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct mg_wifi_scan_bss_data *
3144-
MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL
3145-
MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and chip specific
3146-
MG_TCPIP_EV_DRIVER, // Driver event driver specific
3147-
MG_TCPIP_EV_ST6_CHG, // state6 change uint8_t * (&ifp->state6)
3148-
MG_TCPIP_EV_USER // Starting ID for user events
3138+
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
3139+
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
3140+
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
3141+
MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
3142+
MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
3143+
MG_TCPIP_EV_WIFI_SCAN_RESULT, // Wi-Fi scan results struct
3144+
// mg_wifi_scan_bss_data *
3145+
MG_TCPIP_EV_WIFI_SCAN_END, // Wi-Fi scan has finished NULL
3146+
MG_TCPIP_EV_WIFI_CONNECT_ERR, // Wi-Fi connect has failed driver and
3147+
// chip specific
3148+
MG_TCPIP_EV_DRIVER, // Driver event driver specific
3149+
MG_TCPIP_EV_ST6_CHG, // state6 change uint8_t *
3150+
// (&ifp->state6)
3151+
MG_TCPIP_EV_USER // Starting ID for user events
31493152
};
31503153

31513154
// Network interface
@@ -3161,6 +3164,7 @@ struct mg_tcpip_if {
31613164
bool enable_crc32_check; // Do a CRC check on RX frames and strip it
31623165
bool enable_mac_check; // Do a MAC check on RX frames
31633166
bool update_mac_hash_table; // Signal drivers to update MAC controller
3167+
bool is_ip_changed; // IP address changed, close/restart conns
31643168
struct mg_tcpip_driver *driver; // Low level driver
31653169
void *driver_data; // Driver-specific data
31663170
mg_tcpip_event_handler_t pfn; // Driver-specific event handler function
@@ -3171,11 +3175,13 @@ struct mg_tcpip_if {
31713175
uint16_t mtu; // Interface MTU
31723176
#define MG_TCPIP_MTU_DEFAULT 1500
31733177
#if MG_ENABLE_IPV6
3174-
uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses
3175-
uint8_t prefix_len; // Prefix length
3176-
uint64_t gw6[2]; // Default gateway
3177-
bool enable_slaac; // Enable IPv6 address autoconfiguration
3178-
bool enable_dhcp6_client; // Enable DCHPv6 client
3178+
uint64_t ip6ll[2], ip6[2]; // IPv6 link-local and global addresses
3179+
uint8_t prefix[8]; // IPv6 global address prefix
3180+
uint8_t prefix_len; // Prefix length
3181+
uint64_t gw6[2]; // Default gateway
3182+
bool enable_slaac; // Enable IPv6 address autoconfiguration
3183+
bool enable_dhcp6_client; // Enable DCHPv6 client
3184+
bool is_ip6_changed; // IPv6 address changed, close/restart conns
31793185
#endif
31803186

31813187
// Internal state, user can use it but should not change it
@@ -3196,8 +3202,8 @@ struct mg_tcpip_if {
31963202
#define MG_TCPIP_STATE_IP 3 // Interface is up and has an IP assigned
31973203
#define MG_TCPIP_STATE_READY 4 // Interface has fully come up, ready to work
31983204
#if MG_ENABLE_IPV6
3199-
uint8_t gw6mac[6]; // IPv6 Router's MAC
3200-
uint8_t state6; // Current IPv6 state
3205+
uint8_t gw6mac[6]; // IPv6 Router's MAC
3206+
uint8_t state6; // Current IPv6 state
32013207
#endif
32023208
};
32033209
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
@@ -3231,39 +3237,38 @@ struct mg_tcpip_spi {
32313237
uint8_t (*txn)(void *, uint8_t); // SPI transaction: write 1 byte, read reply
32323238
};
32333239

3234-
32353240
// Alignment and memory section requirements
32363241
#ifndef MG_8BYTE_ALIGNED
32373242
#if defined(__GNUC__)
32383243
#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
32393244
#else
32403245
#define MG_8BYTE_ALIGNED
3241-
#endif // compiler
3242-
#endif // 8BYTE_ALIGNED
3246+
#endif // compiler
3247+
#endif // 8BYTE_ALIGNED
32433248

32443249
#ifndef MG_16BYTE_ALIGNED
32453250
#if defined(__GNUC__)
32463251
#define MG_16BYTE_ALIGNED __attribute__((aligned((16U))))
32473252
#else
32483253
#define MG_16BYTE_ALIGNED
3249-
#endif // compiler
3250-
#endif // 16BYTE_ALIGNED
3254+
#endif // compiler
3255+
#endif // 16BYTE_ALIGNED
32513256

32523257
#ifndef MG_32BYTE_ALIGNED
32533258
#if defined(__GNUC__)
32543259
#define MG_32BYTE_ALIGNED __attribute__((aligned((32U))))
32553260
#else
32563261
#define MG_32BYTE_ALIGNED
3257-
#endif // compiler
3258-
#endif // 32BYTE_ALIGNED
3262+
#endif // compiler
3263+
#endif // 32BYTE_ALIGNED
32593264

32603265
#ifndef MG_64BYTE_ALIGNED
32613266
#if defined(__GNUC__)
32623267
#define MG_64BYTE_ALIGNED __attribute__((aligned((64U))))
32633268
#else
32643269
#define MG_64BYTE_ALIGNED
3265-
#endif // compiler
3266-
#endif // 64BYTE_ALIGNED
3270+
#endif // compiler
3271+
#endif // 64BYTE_ALIGNED
32673272

32683273
#ifndef MG_ETH_RAM
32693274
#define MG_ETH_RAM

src/drivers/tm4c.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,11 @@ enum {
4040
EPHYSTS = 16
4141
}; // PHY constants
4242

43-
static inline void tm4cspin(volatile uint32_t count) {
44-
while (count--) (void) 0;
45-
}
46-
4743
static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
4844
EMAC->EMACMIIADDR &= (0xf << 2);
4945
EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
5046
EMAC->EMACMIIADDR |= MG_BIT(0);
51-
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
47+
while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0;
5248
return EMAC->EMACMIIDATA;
5349
}
5450

@@ -58,7 +54,7 @@ static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
5854
EMAC->EMACMIIADDR |=
5955
((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
6056
EMAC->EMACMIIADDR |= MG_BIT(0);
61-
while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1);
57+
while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0;
6258
}
6359

6460
static uint32_t get_sysclk(void) {
@@ -150,9 +146,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
150146
(uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
151147
}
152148

153-
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
154-
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0)
155-
tm4cspin(1); // Wait until done
149+
EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
150+
while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) (void) 0; // Wait until done
156151

157152
// Set MDC clock divider. If user told us the value, use it. Otherwise, guess
158153
int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;

0 commit comments

Comments
 (0)