This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

udp_with_psm sample. ERROR: Address family not supported by protocol family

Hi,

I am trying out the udp_with_psm example from: https://github.com/Rallare/fw-nrfconnect-nrf/tree/nrf9160_samples/samples/nrf9160/udp_with_psm as a first step in sending data via UDP/IP. I have edited the example by using an ntp host from Sweden and using errno to get plain text error. This is the code I am using:

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
 */

#include <zephyr.h>
#include <net/socket.h>
#include <stdio.h>
#include <uart.h>
#include <string.h>
#include <lte_lc.h>
#include <errno.h>
extern int errno;

#define HOST "gbg1.ntp.se"
#define PORT 123
#define RECV_BUF_SIZE 1024
#define SEND_BUF_SIZE 1024

u8_t recv_buf[RECV_BUF_SIZE];

/* As it is close to impossible to find
 * a proper UDP server, we just connect
 * to a ntp server and read the response
 */
struct ntp_format {
	u8_t flags;
	u8_t stratum; /* stratum */
	u8_t poll; /* poll interval */
	s8_t precision; /* precision */
	u32_t rootdelay; /* root delay */
	u32_t rootdisp; /* root dispersion */
	u32_t refid; /* reference ID */
	u32_t reftime_sec; /* reference time */
	u32_t reftime_frac; /* reference time */
	u32_t org_sec; /* origin timestamp */
	u32_t org_frac; /* origin timestamp */
	u32_t rec_sec; /* receive timestamp */
	u32_t rec_frac; /* receive timestamp */
	u32_t xmt_sec; /* transmit timestamp */
	u32_t xmt_frac; /* transmit timestamp */
};

int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = recv(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_recvfrom(int fd, void *buf, u32_t size, u32_t flags,
		      struct sockaddr *src_addr, socklen_t *addrlen)
{
	int err;

	do {
		err = recvfrom(fd, buf, size, flags, src_addr, addrlen);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags)
{
	int err;

	do {
		err = send(fd, buf, size, flags);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len)
{
	int err;

	do {
		err = connect(fd, local_addr, len);
	} while (err < 0 && errno == EAGAIN);

	return err;
}

void setup_psm(void)
{
	/*
	* GPRS Timer 3 value (octet 3)
	*
	* Bits 5 to 1 represent the binary coded timer value.
	*
	* Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
	* Bits 
	* 8 7 6
	* 0 0 0 value is incremented in multiples of 10 minutes 
	* 0 0 1 value is incremented in multiples of 1 hour 
	* 0 1 0 value is incremented in multiples of 10 hours
	* 0 1 1 value is incremented in multiples of 2 seconds
	* 1 0 0 value is incremented in multiples of 30 seconds
	* 1 0 1 value is incremented in multiples of 1 minute
	* 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
	* 1 1 1 value indicates that the timer is deactivated (NOTE 2).
	*/
	char psm_settings[] = CONFIG_LTE_PSM_REQ_RPTAU;
	printk("PSM bits: %c%c%c\n", psm_settings[0], psm_settings[1],
	       psm_settings[2]);
	printk("PSM Interval: %c%c%c%c%c\n", psm_settings[3], psm_settings[4],
	       psm_settings[5], psm_settings[6], psm_settings[7]);
	int err = lte_lc_psm_req(true);
	if (err < 0) {
		printk("Error setting PSM: %d Errno: %d\n", err, errno);
	}
}

void app_udp_start(void)
{       
        struct addrinfo *res;
	socklen_t addrlen = sizeof(struct sockaddr_storage);
        int err = getaddrinfo(HOST, NULL, NULL, &res);
	if (err < 0) {
		printf("getaddrinfo err: %s\n\r", strerror(errno));
		return;
	}
	((struct sockaddr_in *)res->ai_addr)->sin_port = htons(PORT);
	struct sockaddr_in local_addr;

	local_addr.sin_family = AF_INET;
	local_addr.sin_port = htons(0);
	local_addr.sin_addr.s_addr = 0;

	int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (client_fd < 0) {
		printk("client_fd: %d\n\r", client_fd);
		goto error;
	}

	err = bind(client_fd, (struct sockaddr *)&local_addr,
		   sizeof(local_addr));
	if (err < 0) {
		printk("bind err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	err = connect(client_fd, (struct sockaddr *)res->ai_addr,
		      sizeof(struct sockaddr_in));
	if (err < 0) {
		printk("connect err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	/* Just hard code the packet format */
	u8_t send_buf[sizeof(struct ntp_format)] = { 0xe3 };

	/*err = sendto(client_fd, send_buf, sizeof(send_buf), 0,
		     (struct sockaddr *)res->ai_addr, addrlen);*/
	err = send(client_fd, send_buf, sizeof(send_buf), 0);
	printk("sendto ret: %d\n\r", err);
	if (err < 0) {
		printk("sendto err: %d errno: %d\n\r", err, errno);
		goto error;
	}

	err = blocking_recvfrom(client_fd, recv_buf, sizeof(recv_buf), 0,
				(struct sockaddr *)res->ai_addr, &addrlen);
	if (err < 0) {
		printk("recvfrom err: %d errno: %d\n\r", err, errno);
		goto error;
	} else {
		printk("Got data back: ");
		for (int i = 0; i < err; i++) {
			printk("%x ", recv_buf[i]);
		}
		printk("\n");
	}

error:
	printk("Finished\n");
	(void)close(client_fd);
}

static volatile bool run_udp;

void app_timer_handler(struct k_timer *dummy)
{
	static u32_t minutes;

	minutes++;
	/* This shall match the PSM interval */
	if (minutes % 10 == 0) {
		run_udp = true;
	}
	printk("Elapsed time: %d\n", minutes);
}

K_TIMER_DEFINE(app_timer, app_timer_handler, NULL);

void timer_init(void)
{
	k_timer_start(&app_timer, K_MINUTES(1), K_MINUTES(1));
}

/**@brief Configures modem to provide LTE link. Blocks until link is
 * successfully established.
 */

int main(void)
{
	if (!IS_ENABLED(CONFIG_AT_HOST_LIBRARY)) {
		/* Stop the UART RX for power consumption reasons */
		NRF_UARTE0_NS->TASKS_STOPRX = 1;
	}

	printk("UDP test with PSM\n");
        app_udp_start();
	setup_psm();
	timer_init();
	while (1) {
		k_sleep(500);
		if (run_udp == true) {
			printk("Run UDP\n");
			run_udp = false;
			app_udp_start();
		}
	}
	return 1;
}

I get the following output on my serial port:

So I tried changing from hints.ai_family = AF_UNSPEC; to hints.ai_family = AF_INET; in net_sockets.h but it is still the same problem. I even tried AF_INET6 just to check all possibilities but this does not seem to make any difference. 

Is there some other place this should be edited or have I misunderstood the problem?

Kind regards 

Samuel

  • Update:

    I borrowed some code from the CoAP client sample to make the changes I wanted.

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <zephyr.h>
    #include <net/socket.h>
    #include <stdio.h>
    #include <uart.h>
    #include <string.h>
    #include <lte_lc.h>
    #include <errno.h>
    extern int errno;
    
    static struct sockaddr_storage server;
    
    //#define HOST "gbg1.ntp.se"
    //#define PORT 123
    #define RECV_BUF_SIZE 1024
    #define SEND_BUF_SIZE 1024
    
    u8_t recv_buf[RECV_BUF_SIZE];
    
    /* As it is close to impossible to find
     * a proper UDP server, we just connect
     * to a ntp server and read the response
     */
    struct ntp_format {
    	u8_t flags;
    	u8_t stratum; /* stratum */
    	u8_t poll; /* poll interval */
    	s8_t precision; /* precision */
    	u32_t rootdelay; /* root delay */
    	u32_t rootdisp; /* root dispersion */
    	u32_t refid; /* reference ID */
    	u32_t reftime_sec; /* reference time */
    	u32_t reftime_frac; /* reference time */
    	u32_t org_sec; /* origin timestamp */
    	u32_t org_frac; /* origin timestamp */
    	u32_t rec_sec; /* receive timestamp */
    	u32_t rec_frac; /* receive timestamp */
    	u32_t xmt_sec; /* transmit timestamp */
    	u32_t xmt_frac; /* transmit timestamp */
    };
    
    int blocking_recv(int fd, u8_t *buf, u32_t size, u32_t flags)
    {
    	int err;
    
    	do {
    		err = recv(fd, buf, size, flags);
    	} while (err < 0 && errno == EAGAIN);
    
    	return err;
    }
    
    int blocking_recvfrom(int fd, void *buf, u32_t size, u32_t flags,
    		      struct sockaddr *src_addr, socklen_t *addrlen)
    {
    	int err;
    
    	do {
    		err = recvfrom(fd, buf, size, flags, src_addr, addrlen);
    	} while (err < 0 && errno == EAGAIN);
    
    	return err;
    }
    
    int blocking_send(int fd, u8_t *buf, u32_t size, u32_t flags)
    {
    	int err;
    
    	do {
    		err = send(fd, buf, size, flags);
    	} while (err < 0 && errno == EAGAIN);
    
    	return err;
    }
    
    int blocking_connect(int fd, struct sockaddr *local_addr, socklen_t len)
    {
    	int err;
    
    	do {
    		err = connect(fd, local_addr, len);
    	} while (err < 0 && errno == EAGAIN);
    
    	return err;
    }
    
    void setup_psm(void)
    {
    	/*
    	* GPRS Timer 3 value (octet 3)
    	*
    	* Bits 5 to 1 represent the binary coded timer value.
    	*
    	* Bits 6 to 8 defines the timer value unit for the GPRS timer as follows:
    	* Bits 
    	* 8 7 6
    	* 0 0 0 value is incremented in multiples of 10 minutes 
    	* 0 0 1 value is incremented in multiples of 1 hour 
    	* 0 1 0 value is incremented in multiples of 10 hours
    	* 0 1 1 value is incremented in multiples of 2 seconds
    	* 1 0 0 value is incremented in multiples of 30 seconds
    	* 1 0 1 value is incremented in multiples of 1 minute
    	* 1 1 0 value is incremented in multiples of 320 hours (NOTE 1)
    	* 1 1 1 value indicates that the timer is deactivated (NOTE 2).
    	*/
    	char psm_settings[] = CONFIG_LTE_PSM_REQ_RPTAU;
    	printk("PSM bits: %c%c%c\n", psm_settings[0], psm_settings[1],
    	       psm_settings[2]);
    	printk("PSM Interval: %c%c%c%c%c\n", psm_settings[3], psm_settings[4],
    	       psm_settings[5], psm_settings[6], psm_settings[7]);
    	int err = lte_lc_psm_req(true);
    	if (err < 0) {
    		printk("Error setting PSM: %d Errno: %d\n", err, errno);
    	}
    }
    
    void app_udp_start(void)
    {       
            int err;
    	struct addrinfo *result;
    	socklen_t addrlen = sizeof(struct sockaddr_storage);
            struct addrinfo hints = {
    		.ai_family = AF_INET,
    		.ai_socktype = SOCK_DGRAM
    	};
    
    	err = getaddrinfo(CONFIG_SERVER_HOSTNAME, NULL, &hints, &result);
    	if (err != 0) {
    		printk("ERROR: getaddrinfo failed %d\n", err);
    		return -EIO;
    	}
    
    	if (result == NULL) {
    		printk("ERROR: Address not found\n");
    		return -ENOENT;
    	}
    
    	/* IPv4 Address. */
    	struct sockaddr_in *server4 = ((struct sockaddr_in *)&server);
    
    	server4->sin_addr.s_addr =
    		((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr;
    	server4->sin_family = AF_INET;
    	server4->sin_port = htons(CONFIG_SERVER_PORT);
    
    	printk("IPv4 Address found 0x%08x\n", server4->sin_addr.s_addr);
    
    	/* Free the address. */
    	freeaddrinfo(result);
    	
    	//((struct sockaddr_in *)res->ai_addr)->sin_port = htons(PORT);
    	struct sockaddr_in local_addr;
    
    	local_addr.sin_family = AF_INET;
    	local_addr.sin_port = htons(0);
    	local_addr.sin_addr.s_addr = 0;
    
    	int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
    	if (client_fd < 0) {
    		printk("client_fd: %d\n\r", client_fd);
    		goto error;
    	}
    
    	err = bind(client_fd, (struct sockaddr *)&local_addr,
    		   sizeof(local_addr));
    	if (err < 0) {
    		printk("bind err: %d errno: %d\n\r", err, errno);
    		goto error;
    	}
    
    	err = connect(client_fd, (struct sockaddr *)result->ai_addr,
    		      sizeof(struct sockaddr_in));
    	if (err < 0) {
    		printk("connect err: %d errno: %d\n\r", err, errno);
    		goto error;
    	}
    
    	/* Just hard code the packet format */
    	u8_t send_buf[sizeof(struct ntp_format)] = { 0xe3 };
    
    	/*err = sendto(client_fd, send_buf, sizeof(send_buf), 0,
    		     (struct sockaddr *)res->ai_addr, addrlen);*/
    	err = send(client_fd, send_buf, sizeof(send_buf), 0);
    	printk("sendto ret: %d\n\r", err);
    	if (err < 0) {
    		printk("sendto err: %d errno: %d\n\r", err, errno);
    		goto error;
    	}
    
    	err = blocking_recvfrom(client_fd, recv_buf, sizeof(recv_buf), 0,
    				(struct sockaddr *)result->ai_addr, &addrlen);
    	if (err < 0) {
    		printk("recvfrom err: %d errno: %d\n\r", err, errno);
    		goto error;
    	} else {
    		printk("Got data back: ");
    		for (int i = 0; i < err; i++) {
    			printk("%x ", recv_buf[i]);
    		}
    		printk("\n");
    	}
    
    error:
    	printk("Finished\n");
    	(void)close(client_fd);
    }
    
    static volatile bool run_udp;
    
    void app_timer_handler(struct k_timer *dummy)
    {
    	static u32_t minutes;
    
    	minutes++;
    	/* This shall match the PSM interval */
    	if (minutes % 10 == 0) {
    		run_udp = true;
    	}
    	printk("Elapsed time: %d\n", minutes);
    }
    
    K_TIMER_DEFINE(app_timer, app_timer_handler, NULL);
    
    void timer_init(void)
    {
    	k_timer_start(&app_timer, K_MINUTES(1), K_MINUTES(1));
    }
    
    /**@brief Configures modem to provide LTE link. Blocks until link is
     * successfully established.
     */
    
    int main(void)
    {
    	if (!IS_ENABLED(CONFIG_AT_HOST_LIBRARY)) {
    		/* Stop the UART RX for power consumption reasons */
    		NRF_UARTE0_NS->TASKS_STOPRX = 1;
    	}
    
    	printk("UDP test with PSM\n");
            app_udp_start();
    	setup_psm();
    	timer_init();
    	while (1) {
    		k_sleep(500);
    		if (run_udp == true) {
    			printk("Run UDP\n");
    			run_udp = false;
    			app_udp_start();
    		}
    	}
    	return 1;
    }

    However I still get an error. In this case I get:

    So I guess it is a problem with DNS as suggested in : https://devzone.nordicsemi.com/f/nordic-q-a/44294/using-getaddrinfo-for-dns-lookups-nrf9160-dk.

    I am using an NB-IoT sim-card from Telia in Sweden with the latest firmware: 0.7.0-15.alpha

    Is there a solution to this problem at the moment?

    Kind regards

    Samuel Jönsson

  • Hi Samuel,

    Please make sure you are actually running the nb-iot mode.

    AT%XSYSTEMMODE?

    Then you could try to disable ePCO:

    AT%XEPCO=0  //disables ePCO

    AT+CFUN=0 //saves the settings

    Then you should be able to run the example on the nb-iot network.


    or you could add:

    CONFIG_LTE_LEGACY_PCO_MODE=y
    in the prj.conf file of the project, which does the same thing but inside the application itself.
    Let me know if you have any issues.
Related