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 (at) alten.se> 10 * 11 * Based on iplink_vlan.c by Patrick McHardy <kaber (at) 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 24 static void print_usage(FILE *f) 25 { 26 fprintf(f, 27 "Usage:\tip link add name NAME type hsr slave1 SLAVE1-IF slave2 SLAVE2-IF\n" 28 "\t[ supervision ADDR-BYTE ]\n" 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 } 38 39 static void usage(void) 40 { 41 print_usage(stderr); 42 } 43 44 static int hsr_parse_opt(struct link_util *lu, int argc, char **argv, 45 struct nlmsghdr *n) 46 { 47 int ifindex; 48 unsigned char multicast_spec; 49 50 while (argc > 0) { 51 if (matches(*argv, "supervision") == 0) { 52 NEXT_ARG(); 53 if (get_u8(&multicast_spec, *argv, 0)) 54 invarg("ADDR-BYTE is invalid", *argv); 55 addattr_l(n, 1024, IFLA_HSR_MULTICAST_SPEC, 56 &multicast_spec, 1); 57 } else if (matches(*argv, "slave1") == 0) { 58 NEXT_ARG(); 59 ifindex = ll_name_to_index(*argv); 60 if (ifindex == 0) 61 invarg("No such interface", *argv); 62 addattr_l(n, 1024, IFLA_HSR_SLAVE1, &ifindex, 4); 63 } else if (matches(*argv, "slave2") == 0) { 64 NEXT_ARG(); 65 ifindex = ll_name_to_index(*argv); 66 if (ifindex == 0) 67 invarg("No such interface", *argv); 68 addattr_l(n, 1024, IFLA_HSR_SLAVE2, &ifindex, 4); 69 } else if (matches(*argv, "help") == 0) { 70 usage(); 71 return -1; 72 } else { 73 fprintf(stderr, "hsr: what is \"%s\"?\n", *argv); 74 usage(); 75 return -1; 76 } 77 argc--, argv++; 78 } 79 80 return 0; 81 } 82 83 static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 84 { 85 SPRINT_BUF(b1); 86 87 if (!tb) 88 return; 89 90 if (tb[IFLA_HSR_SLAVE1] && 91 RTA_PAYLOAD(tb[IFLA_HSR_SLAVE1]) < sizeof(__u32)) 92 return; 93 if (tb[IFLA_HSR_SLAVE2] && 94 RTA_PAYLOAD(tb[IFLA_HSR_SLAVE2]) < sizeof(__u32)) 95 return; 96 if (tb[IFLA_HSR_SEQ_NR] && 97 RTA_PAYLOAD(tb[IFLA_HSR_SEQ_NR]) < sizeof(__u16)) 98 return; 99 if (tb[IFLA_HSR_SUPERVISION_ADDR] && 100 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]) < ETH_ALEN) 101 return; 102 103 fprintf(f, "slave1 "); 104 if (tb[IFLA_HSR_SLAVE1]) 105 fprintf(f, "%s ", 106 ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1]))); 107 else 108 fprintf(f, "<none> "); 109 110 fprintf(f, "slave2 "); 111 if (tb[IFLA_HSR_SLAVE2]) 112 fprintf(f, "%s ", 113 ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2]))); 114 else 115 fprintf(f, "<none> "); 116 117 if (tb[IFLA_HSR_SEQ_NR]) 118 fprintf(f, "sequence %d ", 119 rta_getattr_u16(tb[IFLA_HSR_SEQ_NR])); 120 121 if (tb[IFLA_HSR_SUPERVISION_ADDR]) 122 fprintf(f, "supervision %s ", 123 ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]), 124 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]), 125 ARPHRD_VOID, 126 b1, sizeof(b1))); 127 } 128 129 static void hsr_print_help(struct link_util *lu, int argc, char **argv, 130 FILE *f) 131 { 132 print_usage(f); 133 } 134 135 struct link_util hsr_link_util = { 136 .id = "hsr", 137 .maxattr = IFLA_VLAN_MAX, 138 .parse_opt = hsr_parse_opt, 139 .print_opt = hsr_print_opt, 140 .print_help = hsr_print_help, 141 }; 142