Either ipv4 or ipv4v6 PPP and IP stacks are enabled based on 3GPP context

pull/4911/head
Mika Leppänen 2017-08-11 14:57:43 +03:00
parent 457f940a7c
commit dd346ec5a8
10 changed files with 125 additions and 63 deletions

View File

@ -49,7 +49,8 @@ nsapi_error_t EthernetInterface::connect()
return mbed_lwip_bringup_2(_dhcp, false,
_ip_address[0] ? _ip_address : 0,
_netmask[0] ? _netmask : 0,
_gateway[0] ? _gateway : 0);
_gateway[0] ? _gateway : 0,
DEFAULT_STACK);
}
nsapi_error_t EthernetInterface::disconnect()

View File

@ -511,10 +511,10 @@ nsapi_error_t mbed_lwip_init(emac_interface_t *emac)
// Backwards compatibility with people using DEVICE_EMAC
nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
{
return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw);
return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK);
}
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw)
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack)
{
// Check if we've already connected
if (lwip_connected) {
@ -533,7 +533,7 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
}
} else {
if (ppp) {
ret = ppp_lwip_if_init(&lwip_netif);
ret = ppp_lwip_if_init(&lwip_netif, stack);
} else {
ret = mbed_lwip_emac_init(NULL);
}
@ -553,43 +553,49 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq);
#if LWIP_IPV6
if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) {
netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
}
if (stack != IPV4_STACK) {
if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) {
netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
}
#if LWIP_IPV6_MLD
/*
* For hardware/netifs that implement MAC filtering.
* All-nodes link-local is handled by default, so we must let the hardware know
* to allow multicast packets in.
* Should set mld_mac_filter previously. */
if (lwip_netif.mld_mac_filter != NULL) {
ip6_addr_t ip6_allnodes_ll;
ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
}
/*
* For hardware/netifs that implement MAC filtering.
* All-nodes link-local is handled by default, so we must let the hardware know
* to allow multicast packets in.
* Should set mld_mac_filter previously. */
if (lwip_netif.mld_mac_filter != NULL) {
ip6_addr_t ip6_allnodes_ll;
ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
}
#endif /* LWIP_IPV6_MLD */
#if LWIP_IPV6_AUTOCONFIG
/* IPv6 address autoconfiguration not enabled by default */
lwip_netif.ip6_autoconfig_enabled = 1;
/* IPv6 address autoconfiguration not enabled by default */
lwip_netif.ip6_autoconfig_enabled = 1;
} else {
// Disable router solidifications
lwip_netif.rs_count = 0;
}
#endif /* LWIP_IPV6_AUTOCONFIG */
#endif // LWIP_IPV6
#if LWIP_IPV4
if (!dhcp && !ppp) {
ip4_addr_t ip_addr;
ip4_addr_t netmask_addr;
ip4_addr_t gw_addr;
if (stack != IPV6_STACK) {
if (!dhcp && !ppp) {
ip4_addr_t ip_addr;
ip4_addr_t netmask_addr;
ip4_addr_t gw_addr;
if (!inet_aton(ip, &ip_addr) ||
!inet_aton(netmask, &netmask_addr) ||
!inet_aton(gw, &gw_addr)) {
return NSAPI_ERROR_PARAMETER;
if (!inet_aton(ip, &ip_addr) ||
!inet_aton(netmask, &netmask_addr) ||
!inet_aton(gw, &gw_addr)) {
return NSAPI_ERROR_PARAMETER;
}
netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
}
netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
}
#endif
@ -614,13 +620,15 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
}
#if LWIP_DHCP
// Connect to the network
lwip_dhcp = dhcp;
if (stack != IPV6_STACK) {
// Connect to the network
lwip_dhcp = dhcp;
if (lwip_dhcp) {
err_t err = dhcp_start(&lwip_netif);
if (err) {
return NSAPI_ERROR_DHCP_FAILURE;
if (lwip_dhcp) {
err_t err = dhcp_start(&lwip_netif);
if (err) {
return NSAPI_ERROR_DHCP_FAILURE;
}
}
}
#endif
@ -636,17 +644,21 @@ nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const cha
}
#if PREF_ADDR_TIMEOUT
// If address is not for preferred stack waits a while to see
// if preferred stack address is acquired
if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) {
sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
if (stack != IPV4_STACK && stack != IPV6_STACK) {
// If address is not for preferred stack waits a while to see
// if preferred stack address is acquired
if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) {
sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
}
}
#endif
#if BOTH_ADDR_TIMEOUT
// If addresses for both stacks are not available waits a while to
// see if address for both stacks are acquired
if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) {
sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
if (stack != IPV4_STACK && stack != IPV6_STACK) {
// If addresses for both stacks are not available waits a while to
// see if address for both stacks are acquired
if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) {
sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
}
}
#endif

View File

@ -29,7 +29,7 @@ extern "C" {
nsapi_error_t mbed_lwip_init(emac_interface_t *emac);
nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac);
nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw);
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw);
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack);
nsapi_error_t mbed_lwip_bringdown(void);
nsapi_error_t mbed_lwip_bringdown_2(bool ppp);

View File

@ -34,6 +34,16 @@
"value": false,
"macro_name": "NSAPI_PPP_AVAILABLE"
},
"ppp-ipv4-enabled": {
"help": "Enable support for ipv4 PPP interface",
"value": true,
"macro_name": "NSAPI_PPP_IPV4_AVAILABLE"
},
"ppp-ipv6-enabled": {
"help": "Enable support for ipv6 PPP interface",
"value": false,
"macro_name": "NSAPI_PPP_IPV6_AVAILABLE"
},
"use-mbed-trace": {
"help": "Use mbed trace for debug, rather than printf",
"value": false

View File

@ -313,7 +313,7 @@ extern "C" err_t ppp_lwip_disconnect()
return ret;
}
extern "C" nsapi_error_t ppp_lwip_if_init(struct netif *netif)
extern "C" nsapi_error_t ppp_lwip_if_init(struct netif *netif, const nsapi_ip_stack_t stack)
{
if (!prepare_event_queue()) {
return NSAPI_ERROR_NO_MEMORY;
@ -330,9 +330,17 @@ extern "C" nsapi_error_t ppp_lwip_if_init(struct netif *netif)
}
#if LWIP_IPV4
ppp_set_usepeerdns(my_ppp_pcb, true);
if (stack != IPV6_STACK) {
ppp_set_usepeerdns(my_ppp_pcb, true);
}
#endif
if (stack == IPV4_STACK) {
my_ppp_pcb->ipv6cp_disabled = true;
} else if (stack == IPV6_STACK) {
my_ppp_pcb->ipcp_disabled = true;
}
return NSAPI_ERROR_OK;
}
@ -341,7 +349,7 @@ nsapi_error_t nsapi_ppp_error_code()
return connect_error_code;
}
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)> cb, const char *uname, const char *password)
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)> cb, const char *uname, const char *password, const nsapi_ip_stack_t stack)
{
if (my_stream) {
return NSAPI_ERROR_PARAMETER;
@ -354,7 +362,7 @@ nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)
// mustn't start calling input until after connect -
// attach deferred until ppp_lwip_connect, called from mbed_lwip_bringup
nsapi_error_t retcode = mbed_lwip_bringup_2(false, true, NULL, NULL, NULL);
nsapi_error_t retcode = mbed_lwip_bringup_2(false, true, NULL, NULL, NULL, stack);
if (retcode != NSAPI_ERROR_OK && connect_error_code != NSAPI_ERROR_OK) {
return connect_error_code;
@ -388,7 +396,7 @@ const char *nsapi_ppp_get_ip_addr(FileHandle *stream)
}
const char *nsapi_ppp_get_netmask(FileHandle *stream)
{
#if LWIP_IPV6
#if !LWIP_IPV4
return NULL;
#endif
@ -403,7 +411,7 @@ const char *nsapi_ppp_get_netmask(FileHandle *stream)
}
const char *nsapi_ppp_get_gw_addr(FileHandle *stream)
{
#if LWIP_IPV6
#if !LWIP_IPV4
return NULL;
#endif

View File

@ -30,7 +30,7 @@ extern "C" {
*
* @return 0 for success and negative error codes for failure
*/
nsapi_error_t ppp_lwip_if_init(struct netif *netif);
nsapi_error_t ppp_lwip_if_init(struct netif *netif, const nsapi_ip_stack_t stack);
/** Connects to a PPP pipe
*
@ -53,9 +53,9 @@ err_t ppp_lwip_disconnect(void);
/**
* Stubs in case LWIP PPP is not enabled
*/
#define ppp_lwip_if_init(netif) NSAPI_ERROR_UNSUPPORTED
#define ppp_lwip_connect() ERR_IF
#define ppp_lwip_disconnect() ERR_IF
#define ppp_lwip_if_init(netif, stack) NSAPI_ERROR_UNSUPPORTED
#define ppp_lwip_connect() ERR_IF
#define ppp_lwip_disconnect() ERR_IF
#endif //LWIP_PPP_API
#ifdef __cplusplus
}

View File

@ -262,6 +262,7 @@ PPPCellularInterface::PPPCellularInterface(FileHandle *fh, bool debug)
_pwd = NULL;
_fh = fh;
_debug_trace_on = debug;
_stack = DEFAULT_STACK;
dev_info.reg_status_csd = CSD_NOT_REGISTERED_NOT_SEARCHING;
dev_info.reg_status_psd = PSD_NOT_REGISTERED_NOT_SEARCHING;
dev_info.ppp_connection_up = false;
@ -451,21 +452,38 @@ nsapi_error_t PPPCellularInterface::setup_context_and_credentials()
return NSAPI_ERROR_PARAMETER;
}
bool try_ipv6 = false;
#if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE
const char ipv4v6_pdp_type[] = {"IPV4V6"};
const char ipv4_pdp_type[] = {"IP"};
const char *pdp_type = ipv4v6_pdp_type;
_stack = IPV4V6_STACK;
#elif NSAPI_PPP_IPV6_AVAILABLE
const char pdp_type[] = {"IPV6"};
#elif NSAPI_PPP_IPV4_AVAILABLE
const char pdp_type[] = {"IP"};
#endif
const char *auth = _uname && _pwd ? "CHAP:" : "";
retry_without_ipv6:
#if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE
retry_without_dual_stack:
#endif
success = _at->send("AT"
"+FCLASS=0;" // set to connection (ATD) to data mode
"+CGDCONT="CTX",\"%s\",\"%s%s\"",
try_ipv6 ? "IPV4V6" : "IP", auth, _apn
pdp_type, auth, _apn
)
&& _at->recv("OK");
if (!success && try_ipv6) {
try_ipv6 = false;
goto retry_without_ipv6;
#if NSAPI_PPP_IPV4_AVAILABLE && NSAPI_PPP_IPV6_AVAILABLE
if (_stack == IPV4V6_STACK) {
if (!success) {
// fallback to ipv4
pdp_type = ipv4_pdp_type;
_stack = IPV4_STACK;
goto retry_without_dual_stack;
}
}
#endif
if (!success) {
_at->recv("OK");
@ -662,7 +680,7 @@ nsapi_error_t PPPCellularInterface::connect()
/* Initialize PPP
* mbed_ppp_init() is a blocking call, it will block until
* connected, or timeout after 30 seconds*/
retcode = nsapi_ppp_connect(_fh, _connection_status_cb, _uname, _pwd);
retcode = nsapi_ppp_connect(_fh, _connection_status_cb, _uname, _pwd, _stack);
if (retcode == NSAPI_ERROR_OK) {
dev_info.ppp_connection_up = true;
}

View File

@ -252,6 +252,7 @@ private:
const char *_uname;
const char *_pwd;
bool _debug_trace_on;
nsapi_ip_stack_t _stack;
Callback<void(nsapi_error_t)> _connection_status_cb;
void base_initialization();
void setup_at_parser();

View File

@ -36,10 +36,11 @@ NetworkStack *nsapi_ppp_get_stack();
* @param status_cb Optional, user provided callback for connection status
* @param uname Optional, username for the connection
* @param pwd Optional, password for the connection
* @param stack Optional, stack for the connection
*
* @return 0 on success, negative error code on failure
*/
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)> status_cb=0, const char *uname=0, const char *pwd=0);
nsapi_error_t nsapi_ppp_connect(FileHandle *stream, Callback<void(nsapi_error_t)> status_cb=0, const char *uname=0, const char *pwd=0, const nsapi_ip_stack_t stack=DEFAULT_STACK);
/** Close a PPP connection
*

View File

@ -216,6 +216,17 @@ typedef enum nsapi_socket_option {
NSAPI_RCVBUF, /*!< Sets recv buffer size */
} nsapi_socket_option_t;
/** Supported IP protocol versions of IP stack
*
* @enum nsapi_ip_stack
*/
typedef enum nsapi_ip_stack {
DEFAULT_STACK = 0,
IPV4_STACK,
IPV6_STACK,
IPV4V6_STACK
} nsapi_ip_stack_t;
/* Backwards compatibility - previously didn't distinguish stack and socket options */
typedef nsapi_socket_level_t nsapi_level_t;
typedef nsapi_socket_option_t nsapi_option_t;