public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* Re: net/hsr Patch - Help
       [not found]   ` <525CF1F3.2050006@ehu.es>
@ 2013-10-15 19:09     ` Arvid Brodin
  2013-10-15 19:27     ` Arvid Brodin
  1 sibling, 0 replies; 2+ messages in thread
From: Arvid Brodin @ 2013-10-15 19:09 UTC (permalink / raw)
  To: Elías Molina Muñoz
  Cc: netdev@vger.kernel.org, Stephen Hemminger, Javier Boticario,
	balferreira, Joe Perches

On 2013-10-15 09:42, Elías Molina Muñoz wrote:
> El 09/09/2013 20:15, Arvid Brodin escribió:
>> On 2013-09-06 10:25, Elías Molina Muñoz wrote:
>>> Dear Mr. Brodin,
>>> 
>>> I would like to introduce myself. My name is Elías Molina, PhD. 
>>> Student at University of Basque Country (Spain). I am writing to 
>>> enquire about your HSR patch.
>> Hi!
>> 
>>> I have read "This is a patch against net-next (2013-08-21)" in
>>> its last version (v3) so I have tried with several kernel
>>> versions but I do not know which is the repo's correct version
>>> of 
>>> http://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/
>>> .
>>> 
>>> Could you tell me which is the kernel version to apply your
>>> patch?
>> I made an error when I sent that patch, so it won't apply to any
>> kernel version.
>> 
>> The below patch should work (cd to the net-next directory and apply
>> with patch -Np1):
>> 
[removed]

> Dear Mr. Brodin,
>  
> Thanks for getting back to me and I apologize for being so late
> replying.
>  
> I am writing to enquire if, once compiled the kernel with your patch,
> there is a sample application for verifying the correct operation of
> HSR, as you did in http://patchwork.ozlabs.org/patch/191165/ with
> Documentation/networking/hsr/hsr_genl.c
>  
> Thank you very much. Best regards,
>  
> Elías Molina

Hi again,

I'm CC:ing the netdev list and others who've shown interest in HSR, since 
they might be interested as well.

Yes, I have patches for iproute2 (to make it possible to add HSR devices)
and also a "hsrinfo" program which can be used to query an HSR interface 
for statistics, and to listen for any HSR errors detected. The hsrinfo 
program is based on the hsr_genl program that you mention. It requires 
the libnl3 library.

The iproute patch is below (I'll send a separate message with the hsrinfo
code).

(I don't think the patch below will get accepted into iproute2 before 
the HSR patch itself is accepted into the kernel - which I'm beginning to 
doubt it ever will be, unfortunately.)


This patch adds support to iproute2 for adding High-Availability Seamless
Redundancy (HSR) network devices.

Signed-off-by: Arvid Brodin <arvid.brodin@xdin.com>
---
 include/linux/if_link.h | 12 +++++++
 ip/Makefile             |  2 +-
 ip/iplink_hsr.c         | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 99 insertions(+), 1 deletion(-)
 create mode 100644 ip/iplink_hsr.c

diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index d07aeca..bab39e8 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -465,4 +465,16 @@ enum {
 
 #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
 
+/* HSR section */
+
+enum {
+	IFLA_HSR_UNSPEC,
+	IFLA_HSR_SLAVE1,
+	IFLA_HSR_SLAVE2,
+	IFLA_HSR_MULTICAST_SPEC,
+	__IFLA_HSR_MAX,
+};
+
+#define IFLA_HSR_MAX (__IFLA_HSR_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/ip/Makefile b/ip/Makefile
index 48bd4a1..5ef1562 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -5,7 +5,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     iplink_vlan.o link_veth.o link_gre.o iplink_can.o \
     iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o \
     iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \
-    link_iptnl.o
+    link_iptnl.o iplink_hsr.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/iplink_hsr.c b/ip/iplink_hsr.c
new file mode 100644
index 0000000..c7c00d6
--- /dev/null
+++ b/ip/iplink_hsr.c
@@ -0,0 +1,86 @@
+/*
+ * iplink_hsr.c	HSR device support
+ *
+ *              This program is free software; you can redistribute it and/or
+ *              modify it under the terms of the GNU General Public License
+ *              as published by the Free Software Foundation; either version
+ *              2 of the License, or (at your option) any later version.
+ *
+ * Authors:     Arvid Brodin <arvid.brodin@xdin.com>
+ *
+ * 		Based on iplink_vlan.c by Patrick McHardy <kaber@trash.net>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>  /* Needed by linux/if.h for some reason */
+#include <linux/if.h>
+
+#include "utils.h"
+#include "ip_common.h"
+
+static void usage(void)
+{
+	fprintf(stderr,
+"Usage:\tip link add name NAME type hsr slave1 SLAVE1-IF slave2 SLAVE2-IF\n"
+"\t[ multicast ADDR-BYTE ]\n"
+"\n"
+"NAME\n"
+"	name of new hsr device (e.g. hsr0)\n"
+"SLAVE1-IF, SLAVE2-IF\n"
+"	the two slave devices bound to the HSR device\n"
+"ADDR-BYTE\n"
+"	0-255; the last byte of the multicast address used for HSR supervision\n"
+"	frames (default = 0)\n");
+}
+
+static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
+			  struct nlmsghdr *n)
+{
+	int ifindex;
+	unsigned char multicast_spec;
+
+	while (argc > 0) {
+		if (matches(*argv, "multicast") == 0) {
+			NEXT_ARG();
+			if (get_u8(&multicast_spec, *argv, 0))
+				invarg("ADDR-BYTE is invalid", *argv);
+			addattr_l(n, 1024, IFLA_HSR_MULTICAST_SPEC, &multicast_spec, 1);
+		} else if (matches(*argv, "slave1") == 0) {
+			NEXT_ARG();
+			ifindex = ll_name_to_index(*argv);
+			if (ifindex == 0)
+				invarg("No such interface", *argv);
+			addattr_l(n, 1024, IFLA_HSR_SLAVE1, &ifindex, 4);
+		} else if (matches(*argv, "slave2") == 0) {
+			NEXT_ARG();
+			ifindex = ll_name_to_index(*argv);
+			if (ifindex == 0)
+				invarg("No such interface", *argv);
+			addattr_l(n, 1024, IFLA_HSR_SLAVE2, &ifindex, 4);
+		} else if (matches(*argv, "help") == 0) {
+			usage();
+			return -1;
+		} else {
+			fprintf(stderr, "hsr: what is \"%s\"?\n", *argv);
+			usage();
+			return -1;
+		}
+		argc--, argv++;
+	}
+
+	return 0;
+}
+
+static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
+{
+	fprintf(f, "hsr_print_opt() called\n");
+}
+
+struct link_util hsr_link_util = {
+	.id		= "hsr",
+	.maxattr	= IFLA_VLAN_MAX,
+	.parse_opt	= hsr_parse_opt,
+	.print_opt	= hsr_print_opt,
+};
-- 
1.8.1.5



-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: net/hsr Patch - Help
       [not found]   ` <525CF1F3.2050006@ehu.es>
  2013-10-15 19:09     ` net/hsr Patch - Help Arvid Brodin
@ 2013-10-15 19:27     ` Arvid Brodin
  1 sibling, 0 replies; 2+ messages in thread
From: Arvid Brodin @ 2013-10-15 19:27 UTC (permalink / raw)
  To: Elías Molina Muñoz
  Cc: netdev@vger.kernel.org, Stephen Hemminger, Javier Boticario,
	balferreira, Joe Perches

On 2013-10-15 09:42, Elías Molina Muñoz wrote:
> El 09/09/2013 20:15, Arvid Brodin escribió:
>> On 2013-09-06 10:25, Elías Molina Muñoz wrote:
>>> Dear Mr. Brodin,
>>> 
>>> I would like to introduce myself. My name is Elías Molina, PhD. 
>>> Student at University of Basque Country (Spain). I am writing to 
>>> enquire about your HSR patch.
>> Hi!
>> 
>>> I have read "This is a patch against net-next (2013-08-21)" in
>>> its last version (v3) so I have tried with several kernel
>>> versions but I do not know which is the repo's correct version
>>> of 
>>> http://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/
>>> .
>>> 
>>> Could you tell me which is the kernel version to apply your
>>> patch?
>> I made an error when I sent that patch, so it won't apply to any
>> kernel version.
>> 
>> The below patch should work (cd to the net-next directory and apply
>> with patch -Np1):
>> 
[removed]

> Dear Mr. Brodin,
>  
> Thanks for getting back to me and I apologize for being so late
> replying.
>  
> I am writing to enquire if, once compiled the kernel with your patch,
> there is a sample application for verifying the correct operation of
> HSR, as you did in http://patchwork.ozlabs.org/patch/191165/ with
> Documentation/networking/hsr/hsr_genl.c
>  
> Thank you very much. Best regards,
>  
> Elías Molina

Hi again,

I'm CC:ing the netdev list and others who've shown interest in HSR, since 
they might be interested as well.

Yes, I have patches for iproute2 (to make it possible to add HSR devices)
and also a "hsrinfo" program which can be used to query an HSR interface 
for statistics, and to listen for any HSR errors detected. The hsrinfo 
program is based on the hsr_genl program that you mention. It requires 
the libnl3 library.


The hsrinfo program is below (the iproute2 patch was sent in a previous
message). This code is not of the same quality standards as you would 
expect of a kernel/iproute2 patch. The idea is to re-write it so that it
becomes part of iproute2, but I won't spend time on that unless there is
some progress with the HSR kernel patch.


---
diff -Nurp hsrinfo-a/hsr_netlink.h hsrinfo-b/hsr_netlink.h
--- hsrinfo-a/hsr_netlink.h	1970-01-01 01:00:00.000000000 +0100
+++ hsrinfo-b/hsr_netlink.h	2013-10-15 21:21:09.058960618 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2011-2013 Autronica Fire and Security AS
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * Author(s):
+ *	2011-2013 Arvid Brodin, arvid.brodin@xdin.com
+ */
+
+#ifndef __HSR_NETLINK_H
+#define __HSR_NETLINK_H
+
+/* attributes */
+enum {
+	HSR_A_UNSPEC,
+	HSR_A_NODE_ADDR,
+	HSR_A_IFINDEX,
+	HSR_A_IF1_AGE,
+	HSR_A_IF2_AGE,
+	HSR_A_NODE_ADDR_B,
+	HSR_A_IF1_SEQ,
+	HSR_A_IF2_SEQ,
+	HSR_A_IF1_IFINDEX,
+	HSR_A_IF2_IFINDEX,
+	HSR_A_ADDR_B_IFINDEX,
+	__HSR_A_MAX,
+};
+#define HSR_A_MAX (__HSR_A_MAX - 1)
+
+
+#ifdef __KERNEL__
+
+#include <linux/if_ether.h>
+#include <linux/module.h>
+
+int __init hsr_netlink_init(void);
+void __exit hsr_netlink_exit(void);
+
+void hsr_nl_ringerror(unsigned char addr[ETH_ALEN], int dev_idx);
+void hsr_nl_nodedown(unsigned char addr[ETH_ALEN]);
+void hsr_nl_framedrop(int dropcount, int dev_idx);
+void hsr_nl_linkdown(int dev_idx);
+
+
+/*
+ * Generic Netlink HSR family definition
+ */
+
+
+#endif /* __KERNEL__ */
+
+
+
+/* commands */
+enum {
+	HSR_C_UNSPEC,
+	HSR_C_RING_ERROR,
+	HSR_C_NODE_DOWN,
+	HSR_C_GET_NODE_STATUS,
+	HSR_C_SET_NODE_STATUS,
+	HSR_C_GET_NODE_LIST,
+	HSR_C_SET_NODE_LIST,
+	__HSR_C_MAX,
+};
+#define HSR_C_MAX (__HSR_C_MAX - 1)
+
+
+
+#endif /* __HSR_NETLINK_H */
diff -Nurp hsrinfo-a/hsrinfo.c hsrinfo-b/hsrinfo.c
--- hsrinfo-a/hsrinfo.c	1970-01-01 01:00:00.000000000 +0100
+++ hsrinfo-b/hsrinfo.c	2013-10-15 21:23:32.983517217 +0200
@@ -0,0 +1,504 @@
+/*
+ * Copyright 2011-2013 Autronica Fire and Security AS
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * Author(s):
+ *	2011-2013 Arvid Brodin, arvid.brodin@xdin.com
+ *
+ * Userspace example of using Generic Netlink (through libnl-3) to get HSR
+ * ("High-availability Seamless Redundancy") link/network status.
+ */
+
+
+/*
+
+Manual static cross-build:
+
+$ PATH=[toolchain-path]/usr/bin/:${PATH} avr32-unknown-linux-uclibc-gcc -Wall -g -I[toolchain-path]/usr/include/libnl3 -static -L[toolchain-path]/usr/lib hsrinfo.c -o hsrinfo -lnl-genl-3 -lnl-3 -pthread -lm
+
+Native build:
+$ gcc -Wall -g -I /usr/include/libnl3/ -lnl-3 -lnl-genl-3 hsrinfo.c -o hsrinfo-x86
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/attr.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/ctrl.h>
+#include <net/if.h>
+#include <linux/if_ether.h>
+#include "hsr_netlink.h"
+
+struct node_item {
+	struct node_item *next;
+	unsigned char addr[ETH_ALEN];
+};
+
+static struct node_item *node_head = NULL;
+
+static int seq_nr = 10;
+
+
+static void nodelist_clear(struct node_item **ni)
+{
+	if (!*ni)
+		return;
+
+	nodelist_clear(&(*ni)->next);
+
+	free(*ni);
+	(*ni) = NULL;
+}
+
+static void nodelist_add(struct node_item **head, const char addr[ETH_ALEN])
+{
+	struct node_item **ni;
+
+	ni = head;
+	while (*ni)
+		ni = &(*ni)->next;
+
+	*ni = calloc(1, sizeof(struct node_item));
+	if (!*ni)
+		return; // No mem
+
+	memcpy((*ni)->addr, addr, ETH_ALEN);
+}
+
+
+static void print_mac(const unsigned char *addr)
+{
+	int i;
+
+	if (!addr) {
+		printf("(null)           ");
+		return;
+	}
+
+	for (i = 0; i < ETH_ALEN - 1; i++)
+		printf("%02x:", addr[i]);
+	printf("%02x", addr[ETH_ALEN - 1]);
+}
+
+
+static void parse_ring_error(struct genlmsghdr *hdr)
+{
+	struct nlattr *attr;
+	unsigned char *AddrA;
+	int ifindex;
+	char ifname[IF_NAMESIZE];
+	char *nameptr;
+
+	printf("Ring error: ");
+
+	AddrA = NULL;
+	ifindex = -1;
+
+	attr = genlmsg_attrdata(hdr, 0);
+	int remaining = genlmsg_attrlen(hdr, 0);
+	while (nla_ok(attr, remaining)) {
+		switch (attr->nla_type) {
+		case HSR_A_NODE_ADDR:
+			AddrA = nla_data(attr);
+			break;
+		case HSR_A_IFINDEX:
+			ifindex = nla_get_u32(attr);
+			break;
+		default:
+			printf("unknown attribute type: %d\n", attr->nla_type);
+		}
+		attr = nla_next(attr, &remaining);
+	}
+
+	if (!AddrA) {
+		printf("Error: invalid HSR_C_RING_ERROR packet\n");
+		return;
+	}
+
+	nameptr = if_indextoname(ifindex, ifname);
+	if (!nameptr)
+		snprintf(ifname, IF_NAMESIZE, "if%d", ifindex);
+	printf("interface %s, node ", ifname);
+	print_mac(AddrA);
+	printf("\n");
+}
+
+static void parse_node_down(struct genlmsghdr *hdr)
+{
+	struct nlattr *attr;
+	unsigned char *AddrA;
+
+	printf("Node down: ");
+
+	AddrA = NULL;
+
+	attr = genlmsg_attrdata(hdr, 0);
+	int remaining = genlmsg_attrlen(hdr, 0);
+	while (nla_ok(attr, remaining)) {
+		switch (attr->nla_type) {
+		case HSR_A_NODE_ADDR:
+			AddrA = nla_data(attr);
+			break;
+		default:
+			printf("unknown attribute type: %d\n", attr->nla_type);
+		}
+		attr = nla_next(attr, &remaining);
+	}
+
+	if (!AddrA) {
+		printf("Error: invalid HSR_C_NODE_DOWN packet\n");
+		return;
+	}
+
+	print_mac(AddrA);
+	printf("\n");
+}
+
+static void parse_node_status(struct genlmsghdr *hdr)
+{
+	unsigned char *AddrA, *AddrB;
+	int if1_age, if2_age;
+	int if1_seq, if2_seq;
+	int if1_ifindex, if2_ifindex, addr_b_ifindex;
+	char if1_ifname[IF_NAMESIZE];
+	char if2_ifname[IF_NAMESIZE];
+	char addr_b_ifname[IF_NAMESIZE];
+	char *nameptr;
+	struct nlattr *attr;
+
+	AddrA = NULL;
+	AddrB = NULL;
+	if1_age = -1;
+	if2_age = -1;
+	if1_seq = -1;
+	if2_seq = -1;
+	if1_ifindex = -1;
+	if2_ifindex = -1;
+	addr_b_ifindex = -1;
+
+	attr = genlmsg_attrdata(hdr, 0);
+	int remaining = genlmsg_attrlen(hdr, 0);
+	while (nla_ok(attr, remaining)) {
+		switch (attr->nla_type) {
+		case HSR_A_NODE_ADDR:
+			if (AddrA)
+				printf("%s: Too many AddrA in message!\n", __func__);
+			AddrA = nla_data(attr);
+			break;
+		case HSR_A_NODE_ADDR_B:
+			if (AddrB)
+				printf("%s: Too many AddrB in message!\n", __func__);
+			AddrB = nla_data(attr);
+			break;
+		case HSR_A_IFINDEX:
+			break;
+		case HSR_A_IF1_AGE:
+			if1_age = (int) nla_get_u32(attr);
+			break;
+		case HSR_A_IF2_AGE:
+			if2_age = (int) nla_get_u32(attr);
+			break;
+		case HSR_A_IF1_SEQ:
+			if1_seq = nla_get_u16(attr);
+			break;
+		case HSR_A_IF2_SEQ:
+			if2_seq = nla_get_u16(attr);
+			break;
+		case HSR_A_IF1_IFINDEX:
+			if1_ifindex = nla_get_u32(attr);
+			break;
+		case HSR_A_IF2_IFINDEX:
+			if2_ifindex = nla_get_u32(attr);
+			break;
+		case HSR_A_ADDR_B_IFINDEX:
+			addr_b_ifindex = nla_get_u32(attr);
+			break;
+		default:
+			printf("%s: unknown attribute type: %d\n", __func__, attr->nla_type);
+		}
+		attr = nla_next(attr, &remaining);
+	}
+
+	if (!AddrA) {
+		printf("Error: invalid HSR_C_SET_NODE_STATUS packet\n");
+		return;
+	}
+
+	nameptr = if_indextoname(if1_ifindex, if1_ifname);
+	if (!nameptr)
+		snprintf(if1_ifname, IF_NAMESIZE, "if%d", if1_ifindex);
+	nameptr = if_indextoname(if2_ifindex, if2_ifname);
+	if (!nameptr)
+		snprintf(if2_ifname, IF_NAMESIZE, "if%d", if2_ifindex);
+	nameptr = if_indextoname(addr_b_ifindex, addr_b_ifname);
+	if (!nameptr)
+		snprintf(addr_b_ifname, IF_NAMESIZE, "if%d", addr_b_ifindex);
+
+	printf("Node: ");
+	print_mac(AddrA);
+	if (AddrB) {
+		printf("    AddrB: ");
+		print_mac(AddrB);
+		printf(" (over %s)", addr_b_ifname);
+	}
+	printf("\n      Sequence nr (age): %s: %5d (%5d ms); %s: %5d (%5d ms)\n",
+		if1_ifname, if1_seq, if1_age,
+		if2_ifname, if2_seq, if2_age);
+}
+
+static void parse_node_list(struct genlmsghdr *hdr)
+{
+	struct nlattr *attr;
+
+	nodelist_clear(&node_head);
+
+	attr = genlmsg_attrdata(hdr, 0);
+	int remaining = genlmsg_attrlen(hdr, 0);
+	while (nla_ok(attr, remaining)) {
+		switch (attr->nla_type) {
+		case HSR_A_NODE_ADDR:
+			nodelist_add(&node_head, nla_data(attr));
+			break;
+		default:
+			printf("Unknown attribute type for HSR_C_SET_NODE_LIST: %d\n", attr->nla_type);
+		}
+		attr = nla_next(attr, &remaining);
+	}
+}
+
+
+static int parse_genlmsg(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *hdr;
+
+	/*
+	 * Extract command ID from "message" -> "netlink header" ->
+	 * "generic netlink header".
+	 *
+	 * These are the command enums used when creating a genl msg header
+	 * in the kernel with genlmsg_put().
+	 */
+	hdr = genlmsg_hdr(nlmsg_hdr(msg));
+
+//	printf("%d: ", nlmsg_hdr(msg)->nlmsg_seq);
+	switch (hdr->cmd) {
+	case HSR_C_RING_ERROR:
+		parse_ring_error(hdr);
+		break;
+	case HSR_C_NODE_DOWN:
+		parse_node_down(hdr);
+		break;
+	case HSR_C_SET_NODE_STATUS:
+		parse_node_status(hdr);
+		break;
+	case HSR_C_SET_NODE_LIST:
+		parse_node_list(hdr);
+		break;
+	default:
+		printf("Unknown genl message received (%d)\n", hdr->cmd);
+	}
+
+	return 0;
+}
+
+
+static int query_get_node_status(struct nl_sock *nlsk, int family, int ifindex,
+					const unsigned char node_addr[ETH_ALEN])
+{
+	struct nl_msg *msg;
+	void *user_hdr;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	user_hdr = genlmsg_put(msg, NL_AUTO_PORT, seq_nr++, family,
+				0, NLM_F_REQUEST, HSR_C_GET_NODE_STATUS, 1);
+	if (!user_hdr)
+		goto nla_put_failure;
+
+	NLA_PUT_U32(msg, HSR_A_IFINDEX, ifindex);
+	NLA_PUT(msg, HSR_A_NODE_ADDR, ETH_ALEN, node_addr);
+
+/*
+	printf("Querying if %d for status of node ", ifindex);
+	print_mac(node_addr);
+	printf("\n");
+*/
+
+	return (nl_send_auto(nlsk, msg));
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -1;
+}
+
+
+static int query_get_node_list(struct nl_sock *nlsk, int family, int ifindex)
+{
+	struct nl_msg *msg;
+	void *user_hdr;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		return -1;
+
+	user_hdr = genlmsg_put(msg, NL_AUTO_PORT, seq_nr++, family,
+				0, NLM_F_REQUEST, HSR_C_GET_NODE_LIST, 1);
+	if (!user_hdr)
+		goto nla_put_failure;
+
+	NLA_PUT_U32(msg, HSR_A_IFINDEX, ifindex);
+
+//	printf("Querying if %d for node list\n", ifindex);
+
+	return (nl_send_auto(nlsk, msg));
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return -1;
+}
+
+
+
+static void print_usage(const char *name)
+{
+	printf(
+"Usage: %s [-q] interface [node mac address]\n"
+"Display ring error messages for a HSR network interface, or\n"
+"(-q) query the interface node database. The node address parameter is only\n"
+"valid with -q, and limits the output to data about a specific node.\n", name);
+}
+
+
+static const char optstring[] = "+q";
+
+int main(int argc, char **argv)
+{
+	struct nl_sock *nlsk;
+	int hsr_mgroup;
+	int query;
+	int opt, rc;
+	int hsr_ifindex;
+	struct node_item *ni;
+
+	query = 0;
+	opt = getopt(argc, argv, optstring);
+	while (opt != -1) {
+		switch (opt) {
+		case 'q':
+			query = 1;
+			break;
+		default:
+			print_usage(argv[0]);
+			return EXIT_FAILURE;
+		}
+		opt = getopt(argc, argv, optstring);
+	}
+
+
+	nlsk = nl_socket_alloc();
+	if (!nlsk) {
+		printf("nl_socket_alloc() failed\n");
+		return EXIT_FAILURE;
+	}
+	nl_socket_modify_cb(nlsk, NL_CB_VALID, NL_CB_CUSTOM, parse_genlmsg, NULL);
+	genl_connect(nlsk);
+
+	/*
+	 * Sign up for HSR messages
+	 */
+	hsr_mgroup = genl_ctrl_resolve_grp(nlsk, "HSR", "hsr-network");
+	if (hsr_mgroup < 0) {
+		printf("genl_ctrl_resolve_grp() failed: %d\n", hsr_mgroup);
+		rc = EXIT_FAILURE;
+		goto out;
+	}
+
+	nl_socket_disable_seq_check(nlsk);
+
+	if (!query) {
+		if (argc - optind != 1) {
+			print_usage(argv[0]);
+			return EXIT_FAILURE;
+		}
+
+//		printf("Registering for multicast group %d\n", hsr_mgroup);
+		rc = nl_socket_add_memberships(nlsk, hsr_mgroup, 0);
+		if (rc < 0) {
+			printf("nl_socket_add_memberships() failed: %d\n", rc);
+			goto out;
+		}
+
+		while (1)
+			nl_recvmsgs_default(nlsk);
+
+		/* Not reached */
+	}
+
+
+	if (argc - optind < 1) {
+		print_usage(argv[0]);
+		return EXIT_FAILURE;
+	}
+
+	/* The hsr if we send the enquiry to (get it with e.g.
+	 * 'cat /sys/class/net/hsr0/ifindex'): */
+	hsr_ifindex = if_nametoindex(argv[optind]);
+	if (hsr_ifindex == 0) {
+		printf("%s: %s\n", argv[optind], strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	/* Get node list */
+	int hsr_family;
+
+	hsr_family = genl_ctrl_resolve(nlsk, "HSR");
+	if (hsr_family < 0) {
+		printf("genl_ctrl_resolve() failed: %d\n", hsr_family);
+		goto out;
+	}
+
+	rc = query_get_node_list(nlsk, hsr_family, hsr_ifindex);
+//	printf("query_get_node_list() returned %d\n", rc);
+
+	rc = nl_recvmsgs_default(nlsk);
+//	printf("nl_recvmsgs_default() returned %d\n", rc);
+
+	ni = node_head;
+	while (ni) {
+		/*
+		 * Send a query about the status of another node on the HSR network:
+		 */
+		/* The node to enquire about: */
+		//const unsigned char node[ETH_ALEN] = {0x00, 0x24, 0x74, 0x00, 0x17, 0xAD};
+
+		rc = query_get_node_status(nlsk, hsr_family, hsr_ifindex, ni->addr);
+//		printf("query_node_status() returned %d\n", rc);
+
+		ni = ni->next;
+	}
+
+	while (1) {
+		rc = nl_recvmsgs_default(nlsk);
+//		printf("nl_recvmsgs_default() returned %d\n", rc);
+	}
+
+
+	rc = EXIT_SUCCESS;
+out:
+	nl_close(nlsk);
+	nl_socket_free(nlsk);
+	return rc;
+}


-- 
Arvid Brodin | Consultant (Linux)
XDIN AB | Knarrarnäsgatan 7 | SE-164 40 Kista | Sweden | xdin.com

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2013-10-15 19:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <52299175.90302@ehu.es>
     [not found] ` <522E1035.2050503@xdin.com>
     [not found]   ` <525CF1F3.2050006@ehu.es>
2013-10-15 19:09     ` net/hsr Patch - Help Arvid Brodin
2013-10-15 19:27     ` Arvid Brodin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox