Skip to content

Commit f1de47b

Browse files
committed
Multiport linux support
- See doc/multiple_ports.rst for information on how to configure and run a mulitport configuration - Verified on Raspberry Pi with additional USB ethernet interfaces
1 parent 403525b commit f1de47b

26 files changed

+735
-319
lines changed

doc/multiple_ports.rst

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Multiple ports
22
==============
33
This section describes how to configure the p-net stack, sample application
44
and system for multiple network interfaces or ports.
5+
So far, multiple port has only been tested using the linux port.
56

67

78
Terminology
@@ -92,12 +93,40 @@ Run ``ifconfig`` to check that the bridge is up and its network interfaces are a
9293
TX packets 0 bytes 0 (0.0 B)
9394
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
9495

95-
Configuration of p-net stack and sample application (TBD)
96+
Configuration of p-net stack and sample application
9697
---------------------------------------------------------
9798
To run p-net and the sample application with multiple ports a couple
9899
of things need to be done:
99100

100-
* Reconfigure setting ``PNET_MAX_PORT`` to the actual number of physical ports available in the system.
101-
For this example ``PNET_MAX_PORT`` shall be set to 2.
102-
103-
* TBD - update this document when multiport support is implemented
101+
Reconfigure setting ``PNET_MAX_PORT`` to the actual number of physical ports available in the system.
102+
For this example ``PNET_MAX_PORT`` shall be set to 2.
103+
104+
Example of initial log when starting the demo application with a multi port configuration::
105+
106+
pi@pndevice-pi:~/profinet/build $ sudo ./pn_dev -v
107+
** Starting Profinet demo application **
108+
Number of slots: 5 (incl slot for DAP module)
109+
P-net log level: 0 (DEBUG=0, FATAL=4)
110+
App verbosity level: 1
111+
Nbr of ports: 2
112+
Network interfaces: br0,eth0,eth1
113+
Button1 file:
114+
Button2 file:
115+
Station name: rt-labs-dev
116+
Management port: br0 C2:38:F3:A6:0A:66
117+
Physical port [1]: eth0 B8:27:EB:67:14:8A
118+
Physical port [2]: eth1 58:EF:68:B5:11:0F
119+
Current hostname: pndevice-pi
120+
Current IP address: 192.168.0.50
121+
Current Netmask: 255.255.255.0
122+
Current Gateway: 192.168.0.1
123+
Storage directory: /home/pi/profinet/build
124+
125+
Update gsdml file
126+
-----------------
127+
The sample app gsdml file contains a commented out block that defines
128+
a second physical port. In the sample application gsdml file, search for "IDS_P2"
129+
and enable commented out lines as described in the gsdml file.
130+
131+
Note that you will have to the reload gsdml file in all tools you are using and
132+
also the Automated RT tester any time the file is changed.

sample_app/GSDML-V2.4-rtlabs-IODevice-20201211.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@
5959
<MAUTypeItem Value="16"/>
6060
</MAUTypeList>
6161
</PortSubmoduleItem>
62+
<!-- Enable to support additional port. (PNET_MAX_PORT == 2) -->
63+
<!-- Add additional PortSubmoduleItems to support additional ports -->
64+
<!--
65+
<PortSubmoduleItem ID="IDS_P2" SubmoduleIdentNumber="0x00008002" SubslotNumber="32770" TextId="IDT_NAME_PS2" MaxPortRxDelay="350" MaxPortTxDelay="160">
66+
<MAUTypeList>
67+
<MAUTypeItem Value="16"/>
68+
</MAUTypeList>
69+
</PortSubmoduleItem>
70+
-->
6271
</SystemDefinedSubmoduleList>
6372
</DeviceAccessPointItem>
6473
</DeviceAccessPointList>
@@ -195,6 +204,7 @@
195204
<Text TextId="IDT_CUSTOM_LOGBOOK_1" Value="Custom Logbook entry"/>
196205
<Text TextId="IDT_NAME_IS" Value="I"/>
197206
<Text TextId="IDT_NAME_PS1" Value="P1"/>
207+
<Text TextId="IDT_NAME_PS2" Value="P2"/>
198208
<!--module name-->
199209
<Text TextId="TOK_TextId_Module_I8" Value="8 bits I"/>
200210
<Text TextId="TOK_TextId_Module_O8" Value="8 bits O"/>

sample_app/sampleapp_common.c

Lines changed: 235 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,7 @@ static void ip_to_string (pnal_ipaddr_t ip, char * outputstring)
6060
(uint8_t) (ip & 0xFF));
6161
}
6262

63-
/**
64-
* Convert MAC address to string
65-
* @param mac In: MAC address
66-
* @param outputstring Out: Resulting string buffer. Should have size
67-
* PNAL_ETH_ADDRSTR_SIZE.
68-
*/
69-
static void mac_to_string (pnal_ethaddr_t mac, char * outputstring)
63+
void app_mac_to_string (pnal_ethaddr_t mac, char * outputstring)
7064
{
7165
snprintf (
7266
outputstring,
@@ -189,24 +183,20 @@ static const char * ioxs_to_string (pnet_ioxs_values_t ioxs)
189183
}
190184

191185
void app_print_network_details (
192-
pnal_ethaddr_t * p_macbuffer,
193186
pnal_ipaddr_t ip,
194187
pnal_ipaddr_t netmask,
195188
pnal_ipaddr_t gateway)
196189
{
197190
char ip_string[PNAL_INET_ADDRSTR_SIZE]; /* Terminated string */
198191
char netmask_string[PNAL_INET_ADDRSTR_SIZE]; /* Terminated string */
199192
char gateway_string[PNAL_INET_ADDRSTR_SIZE]; /* Terminated string */
200-
char mac_string[PNAL_ETH_ADDRSTR_SIZE]; /* Terminated string */
201193
char hostname_string[PNAL_HOSTNAME_MAX_SIZE]; /* Terminated string */
202194

203-
mac_to_string (*p_macbuffer, mac_string);
204195
ip_to_string (ip, ip_string);
205196
ip_to_string (netmask, netmask_string);
206197
ip_to_string (gateway, gateway_string);
207198
pnal_get_hostname (hostname_string);
208199

209-
printf ("MAC address: %s\n", mac_string);
210200
printf ("Current hostname: %s\n", hostname_string);
211201
printf ("Current IP address: %s\n", ip_string);
212202
printf ("Current Netmask: %s\n", netmask_string);
@@ -1265,6 +1255,7 @@ void app_plug_dap (pnet_t * net, void * arg)
12651255
PNET_MOD_DAP_IDENT,
12661256
PNET_SUBMOD_DAP_IDENT,
12671257
&cfg_dap_data);
1258+
12681259
app_exp_submodule_ind (
12691260
net,
12701261
arg,
@@ -1274,6 +1265,7 @@ void app_plug_dap (pnet_t * net, void * arg)
12741265
PNET_MOD_DAP_IDENT,
12751266
PNET_SUBMOD_DAP_INTERFACE_1_IDENT,
12761267
&cfg_dap_data);
1268+
12771269
app_exp_submodule_ind (
12781270
net,
12791271
arg,
@@ -1283,12 +1275,49 @@ void app_plug_dap (pnet_t * net, void * arg)
12831275
PNET_MOD_DAP_IDENT,
12841276
PNET_SUBMOD_DAP_INTERFACE_1_PORT_1_IDENT,
12851277
&cfg_dap_data);
1278+
1279+
#if PNET_MAX_PORT >= 2
1280+
app_exp_submodule_ind (
1281+
net,
1282+
arg,
1283+
APP_API,
1284+
PNET_SLOT_DAP_IDENT,
1285+
PNET_SUBSLOT_DAP_INTERFACE_1_PORT_2_IDENT,
1286+
PNET_MOD_DAP_IDENT,
1287+
PNET_SUBMOD_DAP_INTERFACE_1_PORT_2_IDENT,
1288+
&cfg_dap_data);
1289+
#endif
1290+
1291+
#if PNET_MAX_PORT >= 3
1292+
app_exp_submodule_ind (
1293+
net,
1294+
arg,
1295+
APP_API,
1296+
PNET_SLOT_DAP_IDENT,
1297+
PNET_SUBSLOT_DAP_INTERFACE_1_PORT_3_IDENT,
1298+
PNET_MOD_DAP_IDENT,
1299+
PNET_SUBMOD_DAP_INTERFACE_1_PORT_3_IDENT,
1300+
&cfg_dap_data);
1301+
#endif
1302+
1303+
#if PNET_MAX_PORT >= 4
1304+
app_exp_submodule_ind (
1305+
net,
1306+
arg,
1307+
APP_API,
1308+
PNET_SLOT_DAP_IDENT,
1309+
PNET_SUBSLOT_DAP_INTERFACE_1_PORT_4_IDENT,
1310+
PNET_MOD_DAP_IDENT,
1311+
PNET_SUBMOD_DAP_INTERFACE_1_PORT_4_IDENT,
1312+
&cfg_dap_data);
1313+
#endif
12861314
}
12871315

12881316
/************ Configuration of product ID, software version etc **************/
12891317

1290-
int app_adjust_stack_configuration (pnet_cfg_t * stack_config)
1318+
int app_pnet_cfg_init_default (pnet_cfg_t * stack_config)
12911319
{
1320+
uint16_t i;
12921321
memset (stack_config, 0, sizeof (pnet_cfg_t));
12931322
stack_config->tick_us = APP_TICK_INTERVAL_US;
12941323

@@ -1363,9 +1392,16 @@ int app_adjust_stack_configuration (pnet_cfg_t * stack_config)
13631392
stack_config->min_device_interval = 32; /* Corresponds to 1 ms */
13641393

13651394
/* LLDP settings */
1366-
strcpy (stack_config->if_cfg.ports[0].port_id, "port-001");
1367-
stack_config->if_cfg.ports[0].rtclass_2_status = 0;
1368-
stack_config->if_cfg.ports[0].rtclass_3_status = 0;
1395+
for (i = 0; i < PNET_MAX_PORT; i++)
1396+
{
1397+
snprintf (
1398+
stack_config->if_cfg.ports[i].port_id,
1399+
PNET_LLDP_PORT_ID_MAX_SIZE,
1400+
"port-%03d",
1401+
i + 1);
1402+
stack_config->if_cfg.ports[i].rtclass_2_status = 0;
1403+
stack_config->if_cfg.ports[i].rtclass_3_status = 0;
1404+
}
13691405

13701406
/* Network configuration */
13711407
stack_config->send_hello = true;
@@ -1379,6 +1415,190 @@ int app_adjust_stack_configuration (pnet_cfg_t * stack_config)
13791415
return 0;
13801416
}
13811417

1418+
/**
1419+
* Initialize a network interface configuration from a network
1420+
* interface name.
1421+
* This includes reading the Ethernet MAC address.
1422+
* If the network interface can not be found or the operation
1423+
* fails to read the mac address from the network interface,
1424+
* error is returned.
1425+
* @param netif_name In: Network interface name
1426+
* @param p_netif Out: Network interface configuration
1427+
* @param verbosity In: Verbosity
1428+
* @return 0 on success
1429+
* -1 on error
1430+
*/
1431+
int app_port_cfg_init (
1432+
const char * netif_name,
1433+
pnet_netif_t * p_netif,
1434+
int verbosity)
1435+
{
1436+
pnal_ethaddr_t mac;
1437+
char mac_string[PNAL_ETH_ADDRSTR_SIZE]; /* Terminated string */
1438+
1439+
int ret = pnal_get_macaddress (netif_name, &mac);
1440+
if (ret != 0)
1441+
{
1442+
printf (
1443+
"Error: The given network interface does not exist: \"%s\"\n",
1444+
netif_name);
1445+
return -1;
1446+
}
1447+
else
1448+
{
1449+
if (verbosity > 0)
1450+
{
1451+
app_mac_to_string (mac, mac_string);
1452+
printf ("%-10s %s\n", netif_name, mac_string);
1453+
}
1454+
}
1455+
1456+
strncpy (p_netif->if_name, netif_name, PNET_INTERFACE_NAME_MAX_SIZE);
1457+
memcpy (p_netif->eth_addr.addr, mac.addr, sizeof (pnal_ethaddr_t));
1458+
1459+
return 0;
1460+
}
1461+
1462+
int app_get_netif_namelist (
1463+
const char * arg_str,
1464+
app_netif_namelist_t * p_if_list,
1465+
int max_port)
1466+
{
1467+
int ret = 0;
1468+
uint16_t i = 0;
1469+
uint16_t j = 0;
1470+
uint16_t if_index = 0;
1471+
uint16_t if_list_size = max_port + 1; /* NELEMENTS (p_if_list->netif) dynamic
1472+
for test. */
1473+
char c;
1474+
1475+
memset (p_if_list, 0, sizeof (*p_if_list));
1476+
c = arg_str[i++];
1477+
while (c != '\0' && if_index < if_list_size)
1478+
{
1479+
if (c != ',')
1480+
{
1481+
p_if_list->netif[if_index].name[j++] = c;
1482+
}
1483+
else
1484+
{
1485+
p_if_list->netif[if_index].name[j++] = '\0';
1486+
j = 0;
1487+
if_index++;
1488+
}
1489+
c = arg_str[i++];
1490+
}
1491+
1492+
if (max_port == 1)
1493+
{
1494+
if (if_index >= max_port)
1495+
{
1496+
printf ("Error: Only 1 network interface expected.\n");
1497+
ret = -1;
1498+
}
1499+
1500+
if (strlen (p_if_list->netif[0].name) == 0)
1501+
{
1502+
printf ("Error: Zero length network interface name.\n");
1503+
ret = -1;
1504+
}
1505+
p_if_list->netif[1] = p_if_list->netif[0];
1506+
}
1507+
1508+
if (max_port > 1)
1509+
{
1510+
if (if_index != max_port)
1511+
{
1512+
printf ("Error: %u network interfaces expected.\n", max_port + 1);
1513+
ret = -1;
1514+
}
1515+
1516+
for (i = 0; i <= max_port; i++)
1517+
{
1518+
if (strlen (p_if_list->netif[i].name) == 0)
1519+
{
1520+
printf ("Error: Zero length network interface name (%d).\n", i);
1521+
ret = -1;
1522+
}
1523+
}
1524+
}
1525+
1526+
return ret;
1527+
}
1528+
1529+
int app_pnet_cfg_init_netifs (
1530+
const char * netif_list_str,
1531+
pnet_cfg_t * p_cfg,
1532+
int verbosity)
1533+
{
1534+
int ret = 0;
1535+
int i = 0;
1536+
pnal_ipaddr_t ip;
1537+
pnal_ipaddr_t netmask;
1538+
pnal_ipaddr_t gateway;
1539+
app_netif_namelist_t if_list;
1540+
1541+
ret = app_get_netif_namelist (netif_list_str, &if_list, PNET_MAX_PORT);
1542+
if (ret != 0)
1543+
{
1544+
return ret;
1545+
}
1546+
1547+
if (verbosity > 0)
1548+
{
1549+
printf ("Management port: ");
1550+
}
1551+
if (
1552+
app_port_cfg_init (
1553+
if_list.netif[0].name,
1554+
&p_cfg->if_cfg.main_port,
1555+
verbosity) != 0)
1556+
{
1557+
return -1;
1558+
}
1559+
1560+
for (i = 1; i <= PNET_MAX_PORT; i++)
1561+
{
1562+
if (verbosity > 0)
1563+
{
1564+
printf ("Physical port [%u]: ", i);
1565+
}
1566+
1567+
if (
1568+
app_port_cfg_init (
1569+
if_list.netif[i].name,
1570+
&p_cfg->if_cfg.ports[i - 1].phy_port,
1571+
verbosity) != 0)
1572+
{
1573+
return -1;
1574+
}
1575+
}
1576+
1577+
/* Read IP, netmask, gateway from operating system */
1578+
ip = pnal_get_ip_address (if_list.netif[0].name);
1579+
netmask = pnal_get_netmask (if_list.netif[0].name);
1580+
gateway = pnal_get_gateway (if_list.netif[0].name);
1581+
1582+
if (gateway == IP_INVALID)
1583+
{
1584+
printf (
1585+
"Error: Invalid gateway IP address for Ethernet interface: %s\n",
1586+
if_list.netif[0].name);
1587+
return -1;
1588+
}
1589+
1590+
if (verbosity > 0)
1591+
{
1592+
app_print_network_details (ip, netmask, gateway);
1593+
}
1594+
1595+
app_copy_ip_to_struct (&p_cfg->if_cfg.ip_cfg.ip_addr, ip);
1596+
app_copy_ip_to_struct (&p_cfg->if_cfg.ip_cfg.ip_gateway, gateway);
1597+
app_copy_ip_to_struct (&p_cfg->if_cfg.ip_cfg.ip_mask, netmask);
1598+
1599+
return ret;
1600+
}
1601+
13821602
/*************************** Helper functions ********************************/
13831603

13841604
void app_copy_ip_to_struct (

0 commit comments

Comments
 (0)