Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/hsr: Added support for HSR v1

This patch adds support for the newer version 1 of the HSR
networking standard. Version 0 is still default and the new
version has to be selected via iproute2.

Main changes are in the supervision frame handling and its
ethertype field.

Signed-off-by: Peter Heise <peter.heise@airbus.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Peter Heise and committed by
David S. Miller
ee1c2797 125c8d12

+126 -63
+1
include/uapi/linux/if_ether.h
··· 92 92 #define ETH_P_TDLS 0x890D /* TDLS */ 93 93 #define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */ 94 94 #define ETH_P_80221 0x8917 /* IEEE 802.21 Media Independent Handover Protocol */ 95 + #define ETH_P_HSR 0x892F /* IEC 62439-3 HSRv1 */ 95 96 #define ETH_P_LOOPBACK 0x9000 /* Ethernet loopback packet, per IEEE 802.3 */ 96 97 #define ETH_P_QINQ1 0x9100 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */ 97 98 #define ETH_P_QINQ2 0x9200 /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
+1
include/uapi/linux/if_link.h
··· 773 773 IFLA_HSR_SLAVE1, 774 774 IFLA_HSR_SLAVE2, 775 775 IFLA_HSR_MULTICAST_SPEC, /* Last byte of supervision addr */ 776 + IFLA_HSR_VERSION, /* HSR version */ 776 777 IFLA_HSR_SUPERVISION_ADDR, /* Supervision frame multicast addr */ 777 778 IFLA_HSR_SEQ_NR, 778 779 __IFLA_HSR_MAX,
+3 -2
net/hsr/Kconfig
··· 18 18 earlier. 19 19 20 20 This code is a "best effort" to comply with the HSR standard as 21 - described in IEC 62439-3:2010 (HSRv0), but no compliancy tests have 22 - been made. 21 + described in IEC 62439-3:2010 (HSRv0) and IEC 62439-3:2012 (HSRv1), 22 + but no compliancy tests have been made. Use iproute2 to select 23 + the version you desire. 23 24 24 25 You need to perform any and all necessary tests yourself before 25 26 relying on this code in a safety critical system!
+46 -34
net/hsr/hsr_device.c
··· 90 90 91 91 hsr = netdev_priv(hsr_dev); 92 92 93 - if ((hsr_dev->operstate == IF_OPER_UP) && (old_operstate != IF_OPER_UP)) { 93 + if ((hsr_dev->operstate == IF_OPER_UP) 94 + && (old_operstate != IF_OPER_UP)) { 94 95 /* Went up */ 95 96 hsr->announce_count = 0; 96 97 hsr->announce_timer.expires = jiffies + ··· 251 250 .parse = eth_header_parse, 252 251 }; 253 252 254 - 255 - /* HSR:2010 supervision frames should be padded so that the whole frame, 256 - * including headers and FCS, is 64 bytes (without VLAN). 257 - */ 258 - static int hsr_pad(int size) 259 - { 260 - const int min_size = ETH_ZLEN - HSR_HLEN - ETH_HLEN; 261 - 262 - if (size >= min_size) 263 - return size; 264 - return min_size; 265 - } 266 - 267 - static void send_hsr_supervision_frame(struct hsr_port *master, u8 type) 253 + static void send_hsr_supervision_frame(struct hsr_port *master, 254 + u8 type, u8 hsrVer) 268 255 { 269 256 struct sk_buff *skb; 270 257 int hlen, tlen; 258 + struct hsr_tag *hsr_tag; 271 259 struct hsr_sup_tag *hsr_stag; 272 260 struct hsr_sup_payload *hsr_sp; 273 261 unsigned long irqflags; 274 262 275 263 hlen = LL_RESERVED_SPACE(master->dev); 276 264 tlen = master->dev->needed_tailroom; 277 - skb = alloc_skb(hsr_pad(sizeof(struct hsr_sup_payload)) + hlen + tlen, 278 - GFP_ATOMIC); 265 + skb = dev_alloc_skb( 266 + sizeof(struct hsr_tag) + 267 + sizeof(struct hsr_sup_tag) + 268 + sizeof(struct hsr_sup_payload) + hlen + tlen); 279 269 280 270 if (skb == NULL) 281 271 return; ··· 274 282 skb_reserve(skb, hlen); 275 283 276 284 skb->dev = master->dev; 277 - skb->protocol = htons(ETH_P_PRP); 285 + skb->protocol = htons(hsrVer ? ETH_P_HSR : ETH_P_PRP); 278 286 skb->priority = TC_PRIO_CONTROL; 279 287 280 - if (dev_hard_header(skb, skb->dev, ETH_P_PRP, 288 + if (dev_hard_header(skb, skb->dev, (hsrVer ? ETH_P_HSR : ETH_P_PRP), 281 289 master->hsr->sup_multicast_addr, 282 290 skb->dev->dev_addr, skb->len) <= 0) 283 291 goto out; 284 292 skb_reset_mac_header(skb); 285 293 286 - hsr_stag = (typeof(hsr_stag)) skb_put(skb, sizeof(*hsr_stag)); 294 + if (hsrVer > 0) { 295 + hsr_tag = (typeof(hsr_tag)) skb_put(skb, sizeof(struct hsr_tag)); 296 + hsr_tag->encap_proto = htons(ETH_P_PRP); 297 + set_hsr_tag_LSDU_size(hsr_tag, HSR_V1_SUP_LSDUSIZE); 298 + } 287 299 288 - set_hsr_stag_path(hsr_stag, 0xf); 289 - set_hsr_stag_HSR_Ver(hsr_stag, 0); 300 + hsr_stag = (typeof(hsr_stag)) skb_put(skb, sizeof(struct hsr_sup_tag)); 301 + set_hsr_stag_path(hsr_stag, (hsrVer ? 0x0 : 0xf)); 302 + set_hsr_stag_HSR_Ver(hsr_stag, hsrVer); 290 303 304 + /* From HSRv1 on we have separate supervision sequence numbers. */ 291 305 spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); 292 - hsr_stag->sequence_nr = htons(master->hsr->sequence_nr); 293 - master->hsr->sequence_nr++; 306 + if (hsrVer > 0) { 307 + hsr_stag->sequence_nr = htons(master->hsr->sup_sequence_nr); 308 + hsr_tag->sequence_nr = htons(master->hsr->sequence_nr); 309 + master->hsr->sup_sequence_nr++; 310 + master->hsr->sequence_nr++; 311 + } else { 312 + hsr_stag->sequence_nr = htons(master->hsr->sequence_nr); 313 + master->hsr->sequence_nr++; 314 + } 294 315 spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); 295 316 296 317 hsr_stag->HSR_TLV_Type = type; 297 - hsr_stag->HSR_TLV_Length = 12; 318 + /* TODO: Why 12 in HSRv0? */ 319 + hsr_stag->HSR_TLV_Length = hsrVer ? sizeof(struct hsr_sup_payload) : 12; 298 320 299 321 /* Payload: MacAddressA */ 300 - hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp)); 322 + hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(struct hsr_sup_payload)); 301 323 ether_addr_copy(hsr_sp->MacAddressA, master->dev->dev_addr); 324 + 325 + skb_put_padto(skb, ETH_ZLEN + HSR_HLEN); 302 326 303 327 hsr_forward_skb(skb, master); 304 328 return; ··· 337 329 rcu_read_lock(); 338 330 master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); 339 331 340 - if (hsr->announce_count < 3) { 341 - send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE); 332 + if (hsr->announce_count < 3 && hsr->protVersion == 0) { 333 + send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE, 334 + hsr->protVersion); 342 335 hsr->announce_count++; 343 - } else { 344 - send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK); 345 - } 346 336 347 - if (hsr->announce_count < 3) 348 337 hsr->announce_timer.expires = jiffies + 349 338 msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); 350 - else 339 + } else { 340 + send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK, 341 + hsr->protVersion); 342 + 351 343 hsr->announce_timer.expires = jiffies + 352 344 msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); 345 + } 353 346 354 347 if (is_admin_up(master->dev)) 355 348 add_timer(&hsr->announce_timer); ··· 437 428 }; 438 429 439 430 int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], 440 - unsigned char multicast_spec) 431 + unsigned char multicast_spec, u8 protocol_version) 441 432 { 442 433 struct hsr_priv *hsr; 443 434 struct hsr_port *port; ··· 459 450 spin_lock_init(&hsr->seqnr_lock); 460 451 /* Overflow soon to find bugs easier: */ 461 452 hsr->sequence_nr = HSR_SEQNR_START; 453 + hsr->sup_sequence_nr = HSR_SUP_SEQNR_START; 462 454 463 455 init_timer(&hsr->announce_timer); 464 456 hsr->announce_timer.function = hsr_announce; ··· 471 461 472 462 ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr); 473 463 hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; 464 + 465 + hsr->protVersion = protocol_version; 474 466 475 467 /* FIXME: should I modify the value of these? 476 468 *
+1 -1
net/hsr/hsr_device.h
··· 17 17 18 18 void hsr_dev_setup(struct net_device *dev); 19 19 int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], 20 - unsigned char multicast_spec); 20 + unsigned char multicast_spec, u8 protocol_version); 21 21 void hsr_check_carrier_and_operstate(struct hsr_priv *hsr); 22 22 bool is_hsr_master(struct net_device *dev); 23 23 int hsr_get_max_mtu(struct hsr_priv *hsr);
+32 -11
net/hsr/hsr_forward.c
··· 50 50 */ 51 51 static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb) 52 52 { 53 - struct hsr_ethhdr_sp *hdr; 53 + struct ethhdr *ethHdr; 54 + struct hsr_sup_tag *hsrSupTag; 55 + struct hsrv1_ethhdr_sp *hsrV1Hdr; 54 56 55 57 WARN_ON_ONCE(!skb_mac_header_was_set(skb)); 56 - hdr = (struct hsr_ethhdr_sp *) skb_mac_header(skb); 58 + ethHdr = (struct ethhdr *) skb_mac_header(skb); 57 59 58 - if (!ether_addr_equal(hdr->ethhdr.h_dest, 60 + /* Correct addr? */ 61 + if (!ether_addr_equal(ethHdr->h_dest, 59 62 hsr->sup_multicast_addr)) 60 63 return false; 61 64 62 - if (get_hsr_stag_path(&hdr->hsr_sup) != 0x0f) 65 + /* Correct ether type?. */ 66 + if (!(ethHdr->h_proto == htons(ETH_P_PRP) 67 + || ethHdr->h_proto == htons(ETH_P_HSR))) 63 68 return false; 64 - if ((hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_ANNOUNCE) && 65 - (hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) 69 + 70 + /* Get the supervision header from correct location. */ 71 + if (ethHdr->h_proto == htons(ETH_P_HSR)) { /* Okay HSRv1. */ 72 + hsrV1Hdr = (struct hsrv1_ethhdr_sp *) skb_mac_header(skb); 73 + if (hsrV1Hdr->hsr.encap_proto != htons(ETH_P_PRP)) 74 + return false; 75 + 76 + hsrSupTag = &hsrV1Hdr->hsr_sup; 77 + } else { 78 + hsrSupTag = &((struct hsrv0_ethhdr_sp *) skb_mac_header(skb))->hsr_sup; 79 + } 80 + 81 + if ((hsrSupTag->HSR_TLV_Type != HSR_TLV_ANNOUNCE) && 82 + (hsrSupTag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) 66 83 return false; 67 - if (hdr->hsr_sup.HSR_TLV_Length != 12) 84 + if ((hsrSupTag->HSR_TLV_Length != 12) && 85 + (hsrSupTag->HSR_TLV_Length != 86 + sizeof(struct hsr_sup_payload))) 68 87 return false; 69 88 70 89 return true; ··· 129 110 130 111 131 112 static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, 132 - struct hsr_port *port) 113 + struct hsr_port *port, u8 protoVersion) 133 114 { 134 115 struct hsr_ethhdr *hsr_ethhdr; 135 116 int lane_id; ··· 150 131 set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); 151 132 hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr); 152 133 hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; 153 - hsr_ethhdr->ethhdr.h_proto = htons(ETH_P_PRP); 134 + hsr_ethhdr->ethhdr.h_proto = htons(protoVersion ? 135 + ETH_P_HSR : ETH_P_PRP); 154 136 } 155 137 156 138 static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, ··· 180 160 memmove(dst, src, movelen); 181 161 skb_reset_mac_header(skb); 182 162 183 - hsr_fill_tag(skb, frame, port); 163 + hsr_fill_tag(skb, frame, port, port->hsr->protVersion); 184 164 185 165 return skb; 186 166 } ··· 340 320 /* FIXME: */ 341 321 WARN_ONCE(1, "HSR: VLAN not yet supported"); 342 322 } 343 - if (ethhdr->h_proto == htons(ETH_P_PRP)) { 323 + if (ethhdr->h_proto == htons(ETH_P_PRP) 324 + || ethhdr->h_proto == htons(ETH_P_HSR)) { 344 325 frame->skb_std = NULL; 345 326 frame->skb_hsr = skb; 346 327 frame->sequence_nr = hsr_get_skb_sequence_nr(skb);
+19 -11
net/hsr/hsr_framereg.c
··· 177 177 return node; 178 178 } 179 179 180 - if (!is_sup) 181 - return NULL; /* Only supervision frame may create node entry */ 180 + /* Everyone may create a node entry, connected node to a HSR device. */ 182 181 183 - if (ethhdr->h_proto == htons(ETH_P_PRP)) { 182 + if (ethhdr->h_proto == htons(ETH_P_PRP) 183 + || ethhdr->h_proto == htons(ETH_P_HSR)) { 184 184 /* Use the existing sequence_nr from the tag as starting point 185 185 * for filtering duplicate frames. 186 186 */ 187 187 seq_out = hsr_get_skb_sequence_nr(skb) - 1; 188 188 } else { 189 189 WARN_ONCE(1, "%s: Non-HSR frame\n", __func__); 190 - seq_out = 0; 190 + seq_out = HSR_SEQNR_START; 191 191 } 192 192 193 193 return hsr_add_node(node_db, ethhdr->h_source, seq_out); ··· 200 200 void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, 201 201 struct hsr_port *port_rcv) 202 202 { 203 + struct ethhdr *ethhdr; 203 204 struct hsr_node *node_real; 204 205 struct hsr_sup_payload *hsr_sp; 205 206 struct list_head *node_db; 206 207 int i; 207 208 208 - skb_pull(skb, sizeof(struct hsr_ethhdr_sp)); 209 - hsr_sp = (struct hsr_sup_payload *) skb->data; 209 + ethhdr = (struct ethhdr *) skb_mac_header(skb); 210 210 211 - if (ether_addr_equal(eth_hdr(skb)->h_source, hsr_sp->MacAddressA)) 212 - /* Not sent from MacAddressB of a PICS_SUBS capable node */ 213 - goto done; 211 + /* Leave the ethernet header. */ 212 + skb_pull(skb, sizeof(struct ethhdr)); 213 + 214 + /* And leave the HSR tag. */ 215 + if (ethhdr->h_proto == htons(ETH_P_HSR)) 216 + skb_pull(skb, sizeof(struct hsr_tag)); 217 + 218 + /* And leave the HSR sup tag. */ 219 + skb_pull(skb, sizeof(struct hsr_sup_tag)); 220 + 221 + hsr_sp = (struct hsr_sup_payload *) skb->data; 214 222 215 223 /* Merge node_curr (registered on MacAddressB) into node_real */ 216 224 node_db = &port_rcv->hsr->node_db; ··· 233 225 /* Node has already been merged */ 234 226 goto done; 235 227 236 - ether_addr_copy(node_real->MacAddressB, eth_hdr(skb)->h_source); 228 + ether_addr_copy(node_real->MacAddressB, ethhdr->h_source); 237 229 for (i = 0; i < HSR_PT_PORTS; i++) { 238 230 if (!node_curr->time_in_stale[i] && 239 231 time_after(node_curr->time_in[i], node_real->time_in[i])) { ··· 249 241 kfree_rcu(node_curr, rcu_head); 250 242 251 243 done: 252 - skb_push(skb, sizeof(struct hsr_ethhdr_sp)); 244 + skb_push(skb, sizeof(struct hsrv1_ethhdr_sp)); 253 245 } 254 246 255 247
+12 -1
net/hsr/hsr_main.h
··· 30 30 */ 31 31 #define MAX_SLAVE_DIFF 3000 /* ms */ 32 32 #define HSR_SEQNR_START (USHRT_MAX - 1024) 33 + #define HSR_SUP_SEQNR_START (HSR_SEQNR_START / 2) 33 34 34 35 35 36 /* How often shall we check for broken ring and remove node entries older than ··· 58 57 } __packed; 59 58 60 59 #define HSR_HLEN 6 60 + 61 + #define HSR_V1_SUP_LSDUSIZE 52 61 62 62 63 /* The helper functions below assumes that 'path' occupies the 4 most 63 64 * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or ··· 134 131 set_hsr_tag_LSDU_size((struct hsr_tag *) hst, HSR_Ver); 135 132 } 136 133 137 - struct hsr_ethhdr_sp { 134 + struct hsrv0_ethhdr_sp { 138 135 struct ethhdr ethhdr; 136 + struct hsr_sup_tag hsr_sup; 137 + } __packed; 138 + 139 + struct hsrv1_ethhdr_sp { 140 + struct ethhdr ethhdr; 141 + struct hsr_tag hsr; 139 142 struct hsr_sup_tag hsr_sup; 140 143 } __packed; 141 144 ··· 171 162 struct timer_list prune_timer; 172 163 int announce_count; 173 164 u16 sequence_nr; 165 + u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ 166 + u8 protVersion; /* Indicate if HSRv0 or HSRv1. */ 174 167 spinlock_t seqnr_lock; /* locking for sequence_nr */ 175 168 unsigned char sup_multicast_addr[ETH_ALEN]; 176 169 };
+8 -2
net/hsr/hsr_netlink.c
··· 23 23 [IFLA_HSR_SLAVE1] = { .type = NLA_U32 }, 24 24 [IFLA_HSR_SLAVE2] = { .type = NLA_U32 }, 25 25 [IFLA_HSR_MULTICAST_SPEC] = { .type = NLA_U8 }, 26 + [IFLA_HSR_VERSION] = { .type = NLA_U8 }, 26 27 [IFLA_HSR_SUPERVISION_ADDR] = { .type = NLA_BINARY, .len = ETH_ALEN }, 27 28 [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 }, 28 29 }; ··· 36 35 struct nlattr *tb[], struct nlattr *data[]) 37 36 { 38 37 struct net_device *link[2]; 39 - unsigned char multicast_spec; 38 + unsigned char multicast_spec, hsr_version; 40 39 41 40 if (!data) { 42 41 netdev_info(dev, "HSR: No slave devices specified\n"); ··· 63 62 else 64 63 multicast_spec = nla_get_u8(data[IFLA_HSR_MULTICAST_SPEC]); 65 64 66 - return hsr_dev_finalize(dev, link, multicast_spec); 65 + if (!data[IFLA_HSR_VERSION]) 66 + hsr_version = 0; 67 + else 68 + hsr_version = nla_get_u8(data[IFLA_HSR_VERSION]); 69 + 70 + return hsr_dev_finalize(dev, link, multicast_spec, hsr_version); 67 71 } 68 72 69 73 static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev)
+3 -1
net/hsr/hsr_slave.c
··· 22 22 { 23 23 struct sk_buff *skb = *pskb; 24 24 struct hsr_port *port; 25 + u16 protocol; 25 26 26 27 if (!skb_mac_header_was_set(skb)) { 27 28 WARN_ONCE(1, "%s: skb invalid", __func__); ··· 38 37 goto finish_consume; 39 38 } 40 39 41 - if (eth_hdr(skb)->h_proto != htons(ETH_P_PRP)) 40 + protocol = eth_hdr(skb)->h_proto; 41 + if (protocol != htons(ETH_P_PRP) && protocol != htons(ETH_P_HSR)) 42 42 goto finish_pass; 43 43 44 44 skb_push(skb, ETH_HLEN);