Skip to content
Permalink
Browse files

samples: net: sock: mgmt: Add network management socket app

A simple application that listens network management events
using BSD socket API.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
  • Loading branch information...
jukkar authored and andrewboie committed Jun 11, 2019
1 parent c0d6831 commit c283016f3d9d0dc52c69d1bae179e9ec9243bd97
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)

include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(sockets_net_mgmt)

target_sources_ifdef(CONFIG_NET_SOCKETS_NET_MGMT app PRIVATE src/main.c)

include($ENV{ZEPHYR_BASE}/samples/net/common/common.cmake)
@@ -0,0 +1,44 @@
.. _sockets-net-mgmt-sample:

Network Management Socket
#########################

Overview
********

The net-mgmt-socket sample application for Zephyr implements a listener
for network management events that the networking subsystem is sending.

The source code for this sample application can be found at:
:zephyr_file:`samples/net/sockets/net_mgmt`.

Requirements
************

- :ref:`networking_with_host`

Building and Running
********************

There are multiple ways to use this application. One of the most common
usage scenario is to run echo-server application inside QEMU. This is
described in :ref:`networking_with_qemu`.

Build net-mgmt socket sample application like this:

.. zephyr-app-commands::
:zephyr-app: samples/net/sockets/net_mgmt
:board: <board to use>
:conf: <config file to use>
:goals: build
:compact:

Example building for the native_posix board:

.. zephyr-app-commands::
:zephyr-app: samples/net/sockets/net_mgmt
:host-os: unix
:board: native_posix
:conf: prj.conf
:goals: run
:compact:
@@ -0,0 +1,42 @@
# Generic networking options
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_POSIX_MAX_FDS=6
CONFIG_NET_SOCKETS_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y

# Kernel options
CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_INIT_STACKS=y

# Logging
CONFIG_NET_LOG=y
CONFIG_LOG=y

# IP address options
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
CONFIG_NET_MAX_CONTEXTS=10

# Network shell
CONFIG_NET_SHELL=y

# Network application options and configuration
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_CONFIG_AUTO_INIT=n

#CONFIG_NET_MGMT_EVENT_LOG_LEVEL_DBG=y
#CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y

# Set the userspace support by default as that was the purpose
# of the sample application.
CONFIG_USERSPACE=y
@@ -0,0 +1,15 @@
common:
harness: net
depends_on: netif
tags: net socket mgmt
sample:
description: Test network management socket
sample
name: net_mgmt socket
tests:
sample.net.sockets.net_mgmt.kernelmode:
extra_configs:
- CONFIG_USERSPACE=n
sample.net.sockets.net_mgmt.usermode:
extra_configs:
- CONFIG_USERSPACE=y
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2019 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <logging/log.h>
LOG_MODULE_REGISTER(net_mgmt_sock_sample, LOG_LEVEL_DBG);

#include <zephyr.h>
#include <errno.h>
#include <stdio.h>
#include <net/socket.h>
#include <net/socket_net_mgmt.h>
#include <net/net_if.h>

#define MAX_BUF_LEN 64
#define STACK_SIZE 1024
#define THREAD_PRIORITY K_PRIO_COOP(8)

/* A test thread that spits out events that we can catch and show to user */
static void trigger_events(void)
{
int operation = 0;
struct net_if_addr *ifaddr_v6;
struct net_if *iface;
struct in6_addr addr_v6;
int ret;

iface = net_if_get_default();

net_ipv6_addr_create(&addr_v6, 0x2001, 0x0db8, 0, 0, 0, 0, 0, 0x0003);

while (1) {
switch (operation) {
case 0:
ifaddr_v6 = net_if_ipv6_addr_add(iface, &addr_v6,
NET_ADDR_MANUAL, 0);
if (!ifaddr_v6) {
LOG_ERR("Cannot add IPv%c address", '6');
break;
}

break;
case 1:
ret = net_if_ipv6_addr_rm(iface, &addr_v6);
if (!ret) {
LOG_ERR("Cannot del IPv%c address", '6');
break;
}

break;
default:
operation = -1;
break;
}

operation++;

k_sleep(K_SECONDS(1));
}
}

K_THREAD_DEFINE(trigger_events_thread_id, STACK_SIZE,
trigger_events, NULL, NULL, NULL,
THREAD_PRIORITY, 0, K_FOREVER);

static void listener(void)
{
struct sockaddr_nm sockaddr;
struct sockaddr_nm event_addr;
socklen_t event_addr_len;
u8_t buf[MAX_BUF_LEN];
int fd, ret;

fd = socket(AF_NET_MGMT, SOCK_DGRAM, NET_MGMT_EVENT_PROTO);
if (fd < 0) {
printk("Cannot create net_mgmt socket (%d)\n", errno);
exit(1);
}

memset(&sockaddr, 0, sizeof(sockaddr));

sockaddr.nm_family = AF_NET_MGMT;
sockaddr.nm_ifindex = 0; /* Any network interface */
sockaddr.nm_pid = (int)k_current_get();
sockaddr.nm_mask = NET_EVENT_IPV6_DAD_SUCCEED |
NET_EVENT_IPV6_ADDR_ADD |
NET_EVENT_IPV6_ADDR_DEL;

ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret < 0) {
printk("Cannot bind net_mgmt socket (%d)\n", errno);
exit(1);
}

while (1) {
struct net_mgmt_msghdr *hdr;

memset(buf, 0, sizeof(buf));
event_addr_len = sizeof(event_addr);

ret = recvfrom(fd, buf, sizeof(buf), 0,
(struct sockaddr *)&event_addr,
&event_addr_len);
if (ret < 0) {
continue;
}

hdr = (struct net_mgmt_msghdr *)buf;

if (hdr->nm_msg_version != NET_MGMT_SOCKET_VERSION_1) {
/* Do not know how to parse the message */
continue;
}

switch (event_addr.nm_mask) {
case NET_EVENT_IPV6_DAD_SUCCEED:
printk("DAD succeed for interface %d\n",
event_addr.nm_ifindex);
break;
case NET_EVENT_IPV6_ADDR_ADD:
printk("IPv6 address added to interface %d\n",
event_addr.nm_ifindex);
break;
case NET_EVENT_IPV6_ADDR_DEL:
printk("IPv6 address removed from interface %d\n",
event_addr.nm_ifindex);
break;
}
}
}

void main(void)
{
/* The thread start to trigger network management events that
* we then can catch.
*/
k_thread_start(trigger_events_thread_id);

if (IS_ENABLED(CONFIG_USERSPACE)) {
k_thread_user_mode_enter((k_thread_entry_t)listener,
NULL, NULL, NULL);
} else {
listener();
}
}

0 comments on commit c283016

Please sign in to comment.
You can’t perform that action at this time.