553 lines
16 KiB
C
553 lines
16 KiB
C
/*********************************************************************
|
|
* _ _ _
|
|
* _ __ | |_ _ | | __ _ | |__ ___
|
|
* | '__|| __|(_)| | / _` || '_ \ / __|
|
|
* | | | |_ _ | || (_| || |_) |\__ \
|
|
* |_| \__|(_)|_| \__,_||_.__/ |___/
|
|
*
|
|
* www.rt-labs.com
|
|
* Copyright 2018 rt-labs AB, Sweden.
|
|
*
|
|
* This software is dual-licensed under GPLv3 and a commercial
|
|
* license. See the file LICENSE.md distributed with this software for
|
|
* full license information.
|
|
********************************************************************/
|
|
|
|
/**
|
|
* @file
|
|
* @brief Definitions for profinet abstraction layer.
|
|
*
|
|
* The Ethernet-related functions should not use \a loc_port_num, but
|
|
* the interface name instead. The lookup from \a loc_port_num to
|
|
* interface name must happen somewhere else in the stack.
|
|
*/
|
|
|
|
#ifndef PNAL_H
|
|
#define PNAL_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#include "options.h"
|
|
#include "pnet_api.h"
|
|
#include "pnal_sys.h"
|
|
|
|
#define PNAL_MAKEU32(a, b, c, d) \
|
|
(((uint32_t)((a)&0xff) << 24) | ((uint32_t)((b)&0xff) << 16) | \
|
|
((uint32_t)((c)&0xff) << 8) | (uint32_t)((d)&0xff))
|
|
|
|
#define PNAL_MAKEU16(a, b) (((uint16_t)((a)&0xff) << 8) | (uint16_t)((b)&0xff))
|
|
|
|
#define PNAL_INET_ADDRSTR_SIZE 16 /** Incl termination */
|
|
#define PNAL_ETH_ADDRSTR_SIZE 18 /** Incl termination */
|
|
#ifndef PNAL_HOSTNAME_MAX_SIZE
|
|
#define PNAL_HOSTNAME_MAX_SIZE 64 /** Incl termination. Value from Linux. */
|
|
#endif
|
|
|
|
/**
|
|
* Ethernet autonegotiation capabilities (not exhaustive)
|
|
*
|
|
* See IEEE 802.3 (Ethernet) ch. 30.6 "Management for link Auto-Negotiation".
|
|
*
|
|
* See IETF RFC 4836 "Definitions of Managed Objects for
|
|
* IEEE 802.3 Medium Attachment Units (MAUs)", object
|
|
* "IANAifMauAutoNegCapBits"
|
|
*/
|
|
#define PNAL_ETH_AUTONEG_CAP_1000BaseT_FULL_DUPLEX BIT (0)
|
|
#define PNAL_ETH_AUTONEG_CAP_1000BaseT_HALF_DUPLEX BIT (1)
|
|
#define PNAL_ETH_AUTONEG_CAP_1000BaseX_FULL_DUPLEX BIT (2)
|
|
#define PNAL_ETH_AUTONEG_CAP_1000BaseX_HALF_DUPLEX BIT (3)
|
|
#define PNAL_ETH_AUTONEG_CAP_100BaseTX_FULL_DUPLEX BIT (10)
|
|
#define PNAL_ETH_AUTONEG_CAP_100BaseTX_HALF_DUPLEX BIT (11)
|
|
#define PNAL_ETH_AUTONEG_CAP_10BaseT_FULL_DUPLEX BIT (13)
|
|
#define PNAL_ETH_AUTONEG_CAP_10BaseT_HALF_DUPLEX BIT (14)
|
|
#define PNAL_ETH_AUTONEG_CAP_UNKNOWN BIT (15)
|
|
|
|
/**
|
|
* Ethernet MAU type (not exhaustive).
|
|
*
|
|
* See IEEE 802.3 (Ethernet) ch. 30.5 "Layer management for medium
|
|
* attachment units (MAUs)".
|
|
*
|
|
* See IETF RFC 4836 "Definitions of Managed Objects for
|
|
* IEEE 802.3 Medium Attachment Units (MAUs)", objects
|
|
* "IANAifMauTypeListBits" and "dot3MauType".
|
|
*
|
|
* See Profinet "5.2.12.3.12 Coding of the field MAUType"
|
|
*/
|
|
typedef enum pnal_eth_mau
|
|
{
|
|
PNAL_ETH_MAU_UNKNOWN = 0x00, /* When link is down */
|
|
PNAL_ETH_MAU_RADIO = 0x00, /* When link is up */
|
|
PNAL_ETH_MAU_COPPER_10BaseT = 0x05,
|
|
PNAL_ETH_MAU_COPPER_100BaseTX_HALF_DUPLEX = 0x0F,
|
|
PNAL_ETH_MAU_COPPER_100BaseTX_FULL_DUPLEX = 0x10,
|
|
PNAL_ETH_MAU_COPPER_1000BaseT_HALF_DUPLEX = 0x1D,
|
|
PNAL_ETH_MAU_COPPER_1000BaseT_FULL_DUPLEX = 0x1E,
|
|
PNAL_ETH_MAU_FIBER_100BaseFX_HALF_DUPLEX = 0x11,
|
|
PNAL_ETH_MAU_FIBER_100BaseFX_FULL_DUPLEX = 0x12,
|
|
PNAL_ETH_MAU_FIBER_1000BaseX_HALF_DUPLEX = 0x15,
|
|
PNAL_ETH_MAU_FIBER_1000BaseX_FULL_DUPLEX = 0x16,
|
|
} pnal_eth_mau_t;
|
|
|
|
/* See Profinet 2.4 section 5.2.28 and annex W */
|
|
typedef struct pnal_port_stats
|
|
{
|
|
uint32_t if_in_octets;
|
|
uint32_t if_out_octets;
|
|
uint32_t if_in_discards;
|
|
uint32_t if_out_discards;
|
|
uint32_t if_in_errors;
|
|
uint32_t if_out_errors;
|
|
} pnal_port_stats_t;
|
|
|
|
/** Set an IP address given by the four byte-parts */
|
|
#define PNAL_IP4_ADDR_TO_U32(ipaddr, a, b, c, d) \
|
|
ipaddr = PNAL_MAKEU32 (a, b, c, d)
|
|
|
|
typedef enum pnal_ethertype
|
|
{
|
|
PNAL_ETHTYPE_IP = 0x0800U,
|
|
PNAL_ETHTYPE_ARP = 0x0806U,
|
|
PNAL_ETHTYPE_VLAN = 0x8100U,
|
|
PNAL_ETHTYPE_PROFINET = 0x8892U,
|
|
PNAL_ETHTYPE_ETHERCAT = 0x88A4U,
|
|
PNAL_ETHTYPE_LLDP = 0x88CCU,
|
|
PNAL_ETHTYPE_ALL = 0xFFFFU,
|
|
} pnal_ethertype_t;
|
|
|
|
/* 255.255.255.255 */
|
|
#ifndef PNAL_IPADDR_NONE
|
|
#define PNAL_IPADDR_NONE ((uint32_t)0xffffffffUL)
|
|
#endif
|
|
/* 127.0.0.1 */
|
|
#ifndef PNAL_IPADDR_LOOPBACK
|
|
#define PNAL_IPADDR_LOOPBACK ((uint32_t)0x7f000001UL)
|
|
#endif
|
|
/* 0.0.0.0 */
|
|
#ifndef PNAL_IPADDR_ANY
|
|
#define PNAL_IPADDR_ANY ((uint32_t)0x00000000UL)
|
|
#endif
|
|
#define PNAL_IPADDR_INVALID PNAL_IPADDR_ANY
|
|
/* 255.255.255.255 */
|
|
#ifndef PNAL_IPADDR_BROADCAST
|
|
#define PNAL_IPADDR_BROADCAST ((uint32_t)0xffffffffUL)
|
|
#endif
|
|
|
|
typedef uint32_t pnal_ipaddr_t;
|
|
typedef uint16_t pnal_ipport_t;
|
|
|
|
/**
|
|
* The Ethernet MAC address.
|
|
*
|
|
* TODO: Remove this and use pnet_ethaddr_t instead
|
|
*/
|
|
typedef struct pnal_ethaddr
|
|
{
|
|
uint8_t addr[6];
|
|
} pnal_ethaddr_t;
|
|
|
|
/**
|
|
* Ethernet link status.
|
|
*
|
|
* See also type pf_lldp_link_status_t.
|
|
*/
|
|
typedef struct pnal_eth_status_t
|
|
{
|
|
/* Is autonegotiation supported on this port? */
|
|
bool is_autonegotiation_supported;
|
|
|
|
/* Is autonegotiation supported on this port? */
|
|
bool is_autonegotiation_enabled;
|
|
|
|
/* Capabilities advertised to link partner during autonegotiation.
|
|
*
|
|
* See macros PNAL_ETH_AUTONEG_CAP_xxx.
|
|
*/
|
|
uint16_t autonegotiation_advertised_capabilities;
|
|
|
|
/* Operational MAU type.
|
|
*
|
|
* This specifies both the physical medium as well as
|
|
* speed and duplex setting used for the link.
|
|
*/
|
|
pnal_eth_mau_t operational_mau_type;
|
|
|
|
/* Corresponds to linux "RUNNING" flag.
|
|
* Up and cable connected
|
|
*/
|
|
bool running;
|
|
} pnal_eth_status_t;
|
|
|
|
/**
|
|
* Get system uptime from the SNMP implementation.
|
|
*
|
|
* This is the sysUpTime, as used by SNMP:
|
|
* "The time (in hundredths of a second) since the network
|
|
* management portion of the system was last re-initialized."
|
|
* - IETF RFC 3418 (SNMP MIB-2).
|
|
*
|
|
* Typically used to store the SNMP-timestamp for incoming LLDP-packets.
|
|
* This timestamp is later reported back to the SNMP implementation, and
|
|
* remote SNMP managers might use it for filtering.
|
|
*
|
|
* The returned value should be the one used by the SNMP implementation.
|
|
* Ask the SNMP implementation for the value, or make sure that this
|
|
* function and the SNMP implementation use the same mechanism to get the
|
|
* value.
|
|
*
|
|
* Starts at 0, with wrap-around after ~497 days.
|
|
*
|
|
* @return System uptime, in units of 10 milliseconds.
|
|
*/
|
|
uint32_t pnal_get_system_uptime_10ms (void);
|
|
|
|
/**
|
|
* Load a binary file.
|
|
*
|
|
* Can load the data into two buffers.
|
|
*
|
|
* @param fullpath In: Full path to the file
|
|
* @param object_1 Out: Data to load, or NULL. Mandatory if size_1 > 0
|
|
* @param size_1 In: Size of object_1.
|
|
* @param object_2 Out: Data to load, or NULL. Mandatory if size_2 > 0
|
|
* @param size_2 In: Size of object_2.
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if not found or an error occurred.
|
|
*/
|
|
int pnal_load_file (
|
|
const char * fullpath,
|
|
void * object_1,
|
|
size_t size_1,
|
|
void * object_2,
|
|
size_t size_2);
|
|
|
|
/**
|
|
* Save a binary file.
|
|
*
|
|
* Can handle two output buffers.
|
|
*
|
|
* @param fullpath In: Full path to the file
|
|
* @param object_1 In: Data to save, or NULL. Mandatory if size_1 > 0
|
|
* @param size_1 In: Size of object_1.
|
|
* @param object_2 In: Data to save, or NULL. Mandatory if size_2 > 0
|
|
* @param size_2 In: Size of object_2.
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int pnal_save_file (
|
|
const char * fullpath,
|
|
const void * object_1,
|
|
size_t size_1,
|
|
const void * object_2,
|
|
size_t size_2);
|
|
|
|
/**
|
|
* Clear a binary file.
|
|
*
|
|
* @param fullpath In: Full path to the file
|
|
*/
|
|
void pnal_clear_file (const char * fullpath);
|
|
|
|
/*
|
|
*/
|
|
|
|
/**
|
|
* Allocate a buffer
|
|
*
|
|
* The resulting \a pnal_buf_t buffer is defined for
|
|
* each operating system, and should at least contain:
|
|
* void * payload;
|
|
* uint16_t len;
|
|
*
|
|
* @param length In: Length, in bytes
|
|
* @return a pnal_buf_t, or NULL at failure
|
|
*/
|
|
pnal_buf_t * pnal_buf_alloc (uint16_t length);
|
|
|
|
/**
|
|
* Free a buffer
|
|
*
|
|
* @param p In: Buffer to free
|
|
*/
|
|
void pnal_buf_free (pnal_buf_t * p);
|
|
|
|
/** Not yet used */
|
|
uint8_t pnal_buf_header (pnal_buf_t * p, int16_t header_size_increment);
|
|
|
|
/**
|
|
* Network interface handle, forward declaration.
|
|
*/
|
|
typedef struct pnal_eth_handle pnal_eth_handle_t;
|
|
|
|
/**
|
|
* The prototype of raw Ethernet reception call-back functions.
|
|
*
|
|
* @param eth_handle InOut: Network interface handle
|
|
* @param arg InOut: User-defined (may be NULL).
|
|
* @param p_buf InOut: The incoming Ethernet frame
|
|
*
|
|
* @return 0 If the frame was NOT handled by this function.
|
|
* 1 If the frame was handled and the buffer freed.
|
|
*/
|
|
typedef int (pnal_eth_callback_t) (
|
|
pnal_eth_handle_t * eth_handle,
|
|
void * arg,
|
|
pnal_buf_t * p_buf);
|
|
|
|
/**
|
|
* Get status of Ethernet link on specified port
|
|
*
|
|
* @param interface_name In: Ethernet interface name, for example eth0
|
|
* @param status Out: Returned link status (autoneg etc)
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int pnal_eth_get_status (
|
|
const char * interface_name,
|
|
pnal_eth_status_t * status);
|
|
|
|
/**
|
|
* Get network interface index
|
|
*
|
|
* The interface index (ifIndex) is the (row) index for the network interface
|
|
* in the table ifTable, which is part of the SNMP MIB-II data structure.
|
|
* See RFC 2863 "The Interfaces Group MIB".
|
|
*
|
|
* @param interface_name In: Ethernet interface name, for example eth0
|
|
*
|
|
* @return The interface index, or 0 if not available.
|
|
*/
|
|
int pnal_get_interface_index (const char * interface_name);
|
|
|
|
/**
|
|
* Get network interface (port) statistics
|
|
*
|
|
* In Profinet naming a physical Ethernet interface is a "port".
|
|
* This corresponds to for example a Linux Ethernet interface.
|
|
*
|
|
* @param interface_name In: Ethernet interface name for example eth0
|
|
* @param port_stats Out: Returned statistics
|
|
*
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int pnal_get_port_statistics (
|
|
const char * interface_name,
|
|
pnal_port_stats_t * port_stats);
|
|
|
|
/**
|
|
* Send raw Ethernet data
|
|
*
|
|
* @param handle In: Ethernet handle
|
|
* @param buf In: Buffer with data to be sent
|
|
* @return The number of bytes sent, or -1 if an error occurred.
|
|
*/
|
|
int pnal_eth_send (pnal_eth_handle_t * handle, pnal_buf_t * buf);
|
|
|
|
/**
|
|
* Initialize receiving of raw Ethernet frames on one interface (in separate
|
|
* thread)
|
|
*
|
|
* @param if_name In: Ethernet interface name
|
|
* @param receive_type In: Ethernet frame types that shall be received
|
|
* by the network interface / port.
|
|
* @param pnal_cfg In: Operating system dependent configuration
|
|
* @param callback In: Callback for received raw Ethernet frames
|
|
* @param arg InOut: User argument passed to the callback
|
|
*
|
|
* @return the Ethernet handle, or NULL if an error occurred.
|
|
*/
|
|
pnal_eth_handle_t * pnal_eth_init (
|
|
const char * if_name,
|
|
pnal_ethertype_t receive_type,
|
|
const pnal_cfg_t * pnal_cfg,
|
|
pnal_eth_callback_t * callback,
|
|
void * arg);
|
|
|
|
/**
|
|
* Open an UDP socket
|
|
*
|
|
* @param addr In: IP address to listen to. Typically used with
|
|
* PNAL_IPADDR_ANY.
|
|
* @param port In: UDP port to listen to.
|
|
* @return Socket ID, or -1 if an error occurred.
|
|
*/
|
|
int pnal_udp_open (pnal_ipaddr_t addr, pnal_ipport_t port);
|
|
|
|
/**
|
|
* Send UDP data
|
|
*
|
|
* @param id In: Socket ID
|
|
* @param dst_addr In: Destination IP address
|
|
* @param dst_port In: Destination UDP port
|
|
* @param data In: Data to be sent
|
|
* @param size In: Size of data
|
|
* @return The number of bytes sent, or -1 if an error occurred.
|
|
*/
|
|
int pnal_udp_sendto (
|
|
uint32_t id,
|
|
pnal_ipaddr_t dst_addr,
|
|
pnal_ipport_t dst_port,
|
|
const uint8_t * data,
|
|
int size);
|
|
|
|
/**
|
|
* Receive UDP data.
|
|
*
|
|
* This is a nonblocking function, and it
|
|
* returns 0 immediately if no data is available.
|
|
*
|
|
* @param id In: Socket ID
|
|
* @param dst_addr Out: Source IP address
|
|
* @param dst_port Out: Source UDP port
|
|
* @param data Out: Received data
|
|
* @param size In: Size of buffer for received data
|
|
* @return The number of bytes received, or -1 if an error occurred.
|
|
*/
|
|
int pnal_udp_recvfrom (
|
|
uint32_t id,
|
|
pnal_ipaddr_t * src_addr,
|
|
pnal_ipport_t * src_port,
|
|
uint8_t * data,
|
|
int size);
|
|
|
|
/**
|
|
* Close an UDP socket
|
|
*
|
|
* @param id In: Socket ID
|
|
*/
|
|
void pnal_udp_close (uint32_t id);
|
|
|
|
/**
|
|
* Configure SNMP server.
|
|
*
|
|
* This function configures a platform-specific SNMP server as to
|
|
* enable a connected SNMP client to read variables from the p-net stack,
|
|
* as well as to write some variables to it.
|
|
*
|
|
* @param net InOut: The p-net stack instance
|
|
* @param pnal_cfg In: Operating system dependent configuration
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int pnal_snmp_init (pnet_t * net, const pnal_cfg_t * pnal_cfg);
|
|
|
|
/**
|
|
* Get network parameters (IP address, netmask etc)
|
|
*
|
|
* For example:
|
|
*
|
|
* IP address Represented by
|
|
* 1.0.0.0 0x01000000 = 16777216
|
|
* 0.0.0.1 0x00000001 = 1
|
|
*
|
|
* @param interface_name In: Ethernet interface name, for example eth0
|
|
* @param p_ipaddr Out: IPv4 address
|
|
* @param p_netmask Out: Netmask
|
|
* @param p_gw Out: Default gateway
|
|
* @param hostname Out: Host name, for example my_laptop_4. Existing
|
|
* buffer should have size
|
|
* PNAL_HOSTNAME_MAX_SIZE.
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int pnal_get_ip_suite (
|
|
const char * interface_name,
|
|
pnal_ipaddr_t * p_ipaddr,
|
|
pnal_ipaddr_t * p_netmask,
|
|
pnal_ipaddr_t * p_gw,
|
|
char * hostname);
|
|
|
|
/**
|
|
* Read the IP address as an integer. For IPv4.
|
|
*
|
|
* For example:
|
|
*
|
|
* IP address Represented by
|
|
* 1.0.0.0 0x01000000 = 16777216
|
|
* 0.0.0.1 0x00000001 = 1
|
|
*
|
|
* @param interface_name In: Name of network interface
|
|
* @return IP address on success and
|
|
* 0 if an error occurred
|
|
*/
|
|
pnal_ipaddr_t pnal_get_ip_address (const char * interface_name);
|
|
|
|
/**
|
|
* Read the netmask as an integer. For IPv4.
|
|
*
|
|
* @param interface_name In: Name of network interface
|
|
* @return netmask
|
|
*/
|
|
pnal_ipaddr_t pnal_get_netmask (const char * interface_name);
|
|
|
|
/**
|
|
* Read the default gateway address as an integer. For IPv4.
|
|
*
|
|
* Assumes the default gateway is found on .1 on same subnet as the IP address.
|
|
*
|
|
* @param interface_name In: Name of network interface
|
|
* @return netmask
|
|
*/
|
|
pnal_ipaddr_t pnal_get_gateway (const char * interface_name);
|
|
|
|
/**
|
|
* Read the MAC address.
|
|
*
|
|
* @param interface_name In: Name of network interface
|
|
* @param mac_addr Out: MAC address
|
|
*
|
|
* @return 0 on success and
|
|
* -1 if no such interface is available
|
|
*/
|
|
int pnal_get_macaddress (const char * interface_name, pnal_ethaddr_t * p_mac);
|
|
|
|
/**
|
|
* Read the current host name
|
|
*
|
|
* @param hostname Out: Host name, for example my_laptop_4. Existing
|
|
* buffer should have size
|
|
* PNAL_HOSTNAME_MAX_SIZE.
|
|
* @return 0 on success and
|
|
* -1 if an error occurred
|
|
*/
|
|
int pnal_get_hostname (char * hostname);
|
|
|
|
/**
|
|
* Set network parameters (IP address, netmask etc)
|
|
*
|
|
* For example:
|
|
*
|
|
* IP address Represented by
|
|
* 1.0.0.0 0x01000000 = 16777216
|
|
* 0.0.0.1 0x00000001 = 1
|
|
*
|
|
* @param interface_name In: Ethernet interface name, for example eth0
|
|
* @param p_ipaddr In: IPv4 address
|
|
* @param p_netmask In: Netmask
|
|
* @param p_gw In: Default gateway
|
|
* @param hostname In: Host name, for example my_laptop_4
|
|
* @param permanent In: 1 if changes are permanent, or 0 if temporary
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int pnal_set_ip_suite (
|
|
const char * interface_name,
|
|
const pnal_ipaddr_t * p_ipaddr,
|
|
const pnal_ipaddr_t * p_netmask,
|
|
const pnal_ipaddr_t * p_gw,
|
|
const char * hostname,
|
|
bool permanent);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* PNAL_H */
|