Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 57 additions & 19 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand 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));
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand 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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
59 changes: 32 additions & 27 deletions mongoose.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 *);
Expand Down Expand Up @@ -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
Expand Down
13 changes: 4 additions & 9 deletions src/drivers/tm4c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
Loading
Loading