]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/iplink_hsr.c
iplink: hsr: add support for creating PRP device similar to HSR
[mirror_iproute2.git] / ip / iplink_hsr.c
CommitLineData
5c0aec93
AB
1/*
2 * iplink_hsr.c HSR device support
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Arvid Brodin <arvid.brodin@alten.se>
10 *
11 * Based on iplink_vlan.c by Patrick McHardy <kaber@trash.net>
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <sys/socket.h> /* Needed by linux/if.h for some reason */
18#include <linux/if.h>
19#include <linux/if_arp.h>
20#include "rt_names.h"
21#include "utils.h"
22#include "ip_common.h"
23
561e650e 24static void print_usage(FILE *f)
5c0aec93 25{
561e650e 26 fprintf(f,
8589eb4e 27 "Usage:\tip link add name NAME type hsr slave1 SLAVE1-IF slave2 SLAVE2-IF\n"
68f02772 28 "\t[ supervision ADDR-BYTE ] [version VERSION] [proto PROTOCOL]\n"
8589eb4e
MC
29 "\n"
30 "NAME\n"
31 " name of new hsr device (e.g. hsr0)\n"
32 "SLAVE1-IF, SLAVE2-IF\n"
33 " the two slave devices bound to the HSR device\n"
34 "ADDR-BYTE\n"
35 " 0-255; the last byte of the multicast address used for HSR supervision\n"
36 " frames (default = 0)\n"
37 "VERSION\n"
68f02772
MK
38 " 0,1; the protocol version to be used. (default = 0)\n"
39 "PROTOCOL\n"
40 " 0 - HSR, 1 - PRP. (default = 0 - HSR)\n");
5c0aec93
AB
41}
42
561e650e 43static void usage(void)
44{
45 print_usage(stderr);
46}
47
5c0aec93
AB
48static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
49 struct nlmsghdr *n)
50{
51 int ifindex;
52 unsigned char multicast_spec;
4273f100 53 unsigned char protocol_version;
68f02772 54 unsigned char protocol = HSR_PROTOCOL_HSR;
5c0aec93
AB
55
56 while (argc > 0) {
57 if (matches(*argv, "supervision") == 0) {
58 NEXT_ARG();
59 if (get_u8(&multicast_spec, *argv, 0))
60 invarg("ADDR-BYTE is invalid", *argv);
61 addattr_l(n, 1024, IFLA_HSR_MULTICAST_SPEC,
62 &multicast_spec, 1);
4273f100
PH
63 } else if (matches(*argv, "version") == 0) {
64 NEXT_ARG();
65 if (!(get_u8(&protocol_version, *argv, 0) == 0 ||
66 get_u8(&protocol_version, *argv, 0) == 1))
67 invarg("version is invalid", *argv);
68 addattr_l(n, 1024, IFLA_HSR_VERSION,
69 &protocol_version, 1);
68f02772
MK
70 } else if (matches(*argv, "proto") == 0) {
71 NEXT_ARG();
72 if (!(get_u8(&protocol, *argv, 0) == HSR_PROTOCOL_HSR ||
73 get_u8(&protocol, *argv, 0) == HSR_PROTOCOL_PRP))
74 invarg("protocol is invalid", *argv);
75 addattr_l(n, 1024, IFLA_HSR_PROTOCOL,
76 &protocol, 1);
5c0aec93
AB
77 } else if (matches(*argv, "slave1") == 0) {
78 NEXT_ARG();
79 ifindex = ll_name_to_index(*argv);
80 if (ifindex == 0)
81 invarg("No such interface", *argv);
82 addattr_l(n, 1024, IFLA_HSR_SLAVE1, &ifindex, 4);
83 } else if (matches(*argv, "slave2") == 0) {
84 NEXT_ARG();
85 ifindex = ll_name_to_index(*argv);
86 if (ifindex == 0)
87 invarg("No such interface", *argv);
88 addattr_l(n, 1024, IFLA_HSR_SLAVE2, &ifindex, 4);
89 } else if (matches(*argv, "help") == 0) {
90 usage();
91 return -1;
92 } else {
93 fprintf(stderr, "hsr: what is \"%s\"?\n", *argv);
94 usage();
95 return -1;
96 }
97 argc--, argv++;
98 }
99
100 return 0;
101}
102
103static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
104{
105 SPRINT_BUF(b1);
106
107 if (!tb)
108 return;
109
110 if (tb[IFLA_HSR_SLAVE1] &&
111 RTA_PAYLOAD(tb[IFLA_HSR_SLAVE1]) < sizeof(__u32))
112 return;
113 if (tb[IFLA_HSR_SLAVE2] &&
114 RTA_PAYLOAD(tb[IFLA_HSR_SLAVE2]) < sizeof(__u32))
115 return;
116 if (tb[IFLA_HSR_SEQ_NR] &&
117 RTA_PAYLOAD(tb[IFLA_HSR_SEQ_NR]) < sizeof(__u16))
118 return;
119 if (tb[IFLA_HSR_SUPERVISION_ADDR] &&
120 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]) < ETH_ALEN)
121 return;
122
5c0aec93 123 if (tb[IFLA_HSR_SLAVE1])
69ffd273
JF
124 print_string(PRINT_ANY,
125 "slave1",
126 "slave1 %s ",
127 ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1])));
5c0aec93 128 else
69ffd273 129 print_null(PRINT_ANY, "slave1", "slave1 %s ", "<none>");
5c0aec93 130
5c0aec93 131 if (tb[IFLA_HSR_SLAVE2])
69ffd273
JF
132 print_string(PRINT_ANY,
133 "slave2",
134 "slave2 %s ",
135 ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2])));
5c0aec93 136 else
69ffd273 137 print_null(PRINT_ANY, "slave2", "slave2 %s ", "<none>");
5c0aec93
AB
138
139 if (tb[IFLA_HSR_SEQ_NR])
69ffd273
JF
140 print_int(PRINT_ANY,
141 "seq_nr",
142 "sequence %d ",
143 rta_getattr_u16(tb[IFLA_HSR_SEQ_NR]));
5c0aec93
AB
144
145 if (tb[IFLA_HSR_SUPERVISION_ADDR])
69ffd273
JF
146 print_string(PRINT_ANY,
147 "supervision_addr",
148 "supervision %s ",
149 ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]),
150 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]),
151 ARPHRD_VOID,
152 b1, sizeof(b1)));
68f02772
MK
153 if (tb[IFLA_HSR_PROTOCOL])
154 print_hhu(PRINT_ANY, "proto", "proto %hhu ",
155 rta_getattr_u8(tb[IFLA_HSR_PROTOCOL]));
5c0aec93
AB
156}
157
561e650e 158static void hsr_print_help(struct link_util *lu, int argc, char **argv,
159 FILE *f)
160{
161 print_usage(f);
162}
163
5c0aec93
AB
164struct link_util hsr_link_util = {
165 .id = "hsr",
e7867c34 166 .maxattr = IFLA_HSR_MAX,
5c0aec93
AB
167 .parse_opt = hsr_parse_opt,
168 .print_opt = hsr_print_opt,
561e650e 169 .print_help = hsr_print_help,
5c0aec93 170};