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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-hsr-add-support-for-hsr-san-redbox'

Lukasz Majewski says:

====================
net: hsr: Add support for HSR-SAN (RedBOX)

This patch set provides v6 of HSR-SAN (RedBOX) as well as hsr_redbox.sh
test script.

The most straightforward way to test those patches is to use buildroot
(2024.02.01) to create rootfs and QEMU based environment to run x86_64
Linux.

Then one shall run hsr_redbox.sh and hsr_ping.sh from
tools/testing/selftests/net/hsr.
====================

Link: https://lore.kernel.org/r/20240423124908.2073400-1-lukma@denx.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+387 -118
+1
include/uapi/linux/if_link.h
··· 1771 1771 IFLA_HSR_PROTOCOL, /* Indicate different protocol than 1772 1772 * HSR. For example PRP. 1773 1773 */ 1774 + IFLA_HSR_INTERLINK, /* HSR interlink network device */ 1774 1775 __IFLA_HSR_MAX, 1775 1776 }; 1776 1777
+34 -2
net/hsr/hsr_device.c
··· 146 146 case HSR_PT_SLAVE_B: 147 147 designation = "Slave B"; 148 148 break; 149 + case HSR_PT_INTERLINK: 150 + designation = "Interlink"; 151 + break; 149 152 default: 150 153 designation = "Unknown"; 151 154 } ··· 288 285 struct hsr_priv *hsr = master->hsr; 289 286 __u8 type = HSR_TLV_LIFE_CHECK; 290 287 struct hsr_sup_payload *hsr_sp; 288 + struct hsr_sup_tlv *hsr_stlv; 291 289 struct hsr_sup_tag *hsr_stag; 292 290 struct sk_buff *skb; 293 291 ··· 327 323 /* Payload: MacAddressA */ 328 324 hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); 329 325 ether_addr_copy(hsr_sp->macaddress_A, master->dev->dev_addr); 326 + 327 + if (hsr->redbox) { 328 + hsr_stlv = skb_put(skb, sizeof(struct hsr_sup_tlv)); 329 + hsr_stlv->HSR_TLV_type = PRP_TLV_REDBOX_MAC; 330 + hsr_stlv->HSR_TLV_length = sizeof(struct hsr_sup_payload); 331 + 332 + /* Payload: MacAddressRedBox */ 333 + hsr_sp = skb_put(skb, sizeof(struct hsr_sup_payload)); 334 + ether_addr_copy(hsr_sp->macaddress_A, hsr->macaddress_redbox); 335 + } 330 336 331 337 if (skb_put_padto(skb, ETH_ZLEN)) { 332 338 spin_unlock_bh(&hsr->seqnr_lock); ··· 416 402 hsr_del_port(port); 417 403 418 404 port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); 405 + if (port) 406 + hsr_del_port(port); 407 + 408 + port = hsr_port_get_hsr(hsr, HSR_PT_INTERLINK); 419 409 if (port) 420 410 hsr_del_port(port); 421 411 ··· 552 534 }; 553 535 554 536 int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], 555 - unsigned char multicast_spec, u8 protocol_version, 556 - struct netlink_ext_ack *extack) 537 + struct net_device *interlink, unsigned char multicast_spec, 538 + u8 protocol_version, struct netlink_ext_ack *extack) 557 539 { 558 540 bool unregister = false; 559 541 struct hsr_priv *hsr; ··· 562 544 hsr = netdev_priv(hsr_dev); 563 545 INIT_LIST_HEAD(&hsr->ports); 564 546 INIT_LIST_HEAD(&hsr->node_db); 547 + INIT_LIST_HEAD(&hsr->proxy_node_db); 565 548 spin_lock_init(&hsr->list_lock); 566 549 567 550 eth_hw_addr_set(hsr_dev, slave[0]->dev_addr); ··· 588 569 /* Overflow soon to find bugs easier: */ 589 570 hsr->sequence_nr = HSR_SEQNR_START; 590 571 hsr->sup_sequence_nr = HSR_SUP_SEQNR_START; 572 + hsr->interlink_sequence_nr = HSR_SEQNR_START; 591 573 592 574 timer_setup(&hsr->announce_timer, hsr_announce, 0); 593 575 timer_setup(&hsr->prune_timer, hsr_prune_nodes, 0); ··· 623 603 res = hsr_add_port(hsr, slave[1], HSR_PT_SLAVE_B, extack); 624 604 if (res) 625 605 goto err_unregister; 606 + 607 + if (interlink) { 608 + res = hsr_add_port(hsr, interlink, HSR_PT_INTERLINK, extack); 609 + if (res) 610 + goto err_unregister; 611 + 612 + hsr->redbox = true; 613 + ether_addr_copy(hsr->macaddress_redbox, interlink->dev_addr); 614 + timer_setup(&hsr->prune_proxy_timer, hsr_prune_proxy_nodes, 0); 615 + mod_timer(&hsr->prune_proxy_timer, 616 + jiffies + msecs_to_jiffies(PRUNE_PROXY_PERIOD)); 617 + } 626 618 627 619 hsr_debugfs_init(hsr, hsr_dev); 628 620 mod_timer(&hsr->prune_timer, jiffies + msecs_to_jiffies(PRUNE_PERIOD));
+2 -2
net/hsr/hsr_device.h
··· 16 16 void hsr_del_ports(struct hsr_priv *hsr); 17 17 void hsr_dev_setup(struct net_device *dev); 18 18 int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], 19 - unsigned char multicast_spec, u8 protocol_version, 20 - struct netlink_ext_ack *extack); 19 + struct net_device *interlink, unsigned char multicast_spec, 20 + u8 protocol_version, struct netlink_ext_ack *extack); 21 21 void hsr_check_carrier_and_operstate(struct hsr_priv *hsr); 22 22 int hsr_get_max_mtu(struct hsr_priv *hsr); 23 23 #endif /* __HSR_DEVICE_H */
+76 -9
net/hsr/hsr_forward.c
··· 377 377 */ 378 378 ether_addr_copy(eth_hdr(skb)->h_source, port->dev->dev_addr); 379 379 } 380 + 381 + /* When HSR node is used as RedBox - the frame received from HSR ring 382 + * requires source MAC address (SA) replacement to one which can be 383 + * recognized by SAN devices (otherwise, frames are dropped by switch) 384 + */ 385 + if (port->type == HSR_PT_INTERLINK) 386 + ether_addr_copy(eth_hdr(skb)->h_source, 387 + port->hsr->macaddress_redbox); 388 + 380 389 return dev_queue_xmit(skb); 381 390 } 382 391 ··· 399 390 400 391 bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port) 401 392 { 393 + struct sk_buff *skb; 394 + 402 395 if (port->dev->features & NETIF_F_HW_HSR_FWD) 403 396 return prp_drop_frame(frame, port); 397 + 398 + /* RedBox specific frames dropping policies 399 + * 400 + * Do not send HSR supervisory frames to SAN devices 401 + */ 402 + if (frame->is_supervision && port->type == HSR_PT_INTERLINK) 403 + return true; 404 + 405 + /* Do not forward to other HSR port (A or B) unicast frames which 406 + * are addressed to interlink port (and are in the ProxyNodeTable). 407 + */ 408 + skb = frame->skb_hsr; 409 + if (skb && prp_drop_frame(frame, port) && 410 + is_unicast_ether_addr(eth_hdr(skb)->h_dest) && 411 + hsr_is_node_in_db(&port->hsr->proxy_node_db, 412 + eth_hdr(skb)->h_dest)) { 413 + return true; 414 + } 415 + 416 + /* Do not forward to port C (Interlink) frames from nodes A and B 417 + * if DA is in NodeTable. 418 + */ 419 + if ((frame->port_rcv->type == HSR_PT_SLAVE_A || 420 + frame->port_rcv->type == HSR_PT_SLAVE_B) && 421 + port->type == HSR_PT_INTERLINK) { 422 + skb = frame->skb_hsr; 423 + if (skb && is_unicast_ether_addr(eth_hdr(skb)->h_dest) && 424 + hsr_is_node_in_db(&port->hsr->node_db, 425 + eth_hdr(skb)->h_dest)) { 426 + return true; 427 + } 428 + } 429 + 430 + /* Do not forward to port A and B unicast frames received on the 431 + * interlink port if it is addressed to one of nodes registered in 432 + * the ProxyNodeTable. 433 + */ 434 + if ((port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) && 435 + frame->port_rcv->type == HSR_PT_INTERLINK) { 436 + skb = frame->skb_std; 437 + if (skb && is_unicast_ether_addr(eth_hdr(skb)->h_dest) && 438 + hsr_is_node_in_db(&port->hsr->proxy_node_db, 439 + eth_hdr(skb)->h_dest)) { 440 + return true; 441 + } 442 + } 404 443 405 444 return false; 406 445 } ··· 505 448 } 506 449 507 450 /* Check if frame is to be dropped. Eg. for PRP no forward 508 - * between ports. 451 + * between ports, or sending HSR supervision to RedBox. 509 452 */ 510 453 if (hsr->proto_ops->drop_frame && 511 454 hsr->proto_ops->drop_frame(frame, port)) 512 455 continue; 513 456 514 - if (port->type != HSR_PT_MASTER) 457 + if (port->type == HSR_PT_SLAVE_A || 458 + port->type == HSR_PT_SLAVE_B) 515 459 skb = hsr->proto_ops->create_tagged_frame(frame, port); 516 460 else 517 461 skb = hsr->proto_ops->get_untagged_frame(frame, port); ··· 527 469 hsr_deliver_master(skb, port->dev, frame->node_src); 528 470 } else { 529 471 if (!hsr_xmit(skb, port, frame)) 530 - sent = true; 472 + if (port->type == HSR_PT_SLAVE_A || 473 + port->type == HSR_PT_SLAVE_B) 474 + sent = true; 531 475 } 532 476 } 533 477 } ··· 563 503 frame->skb_prp = NULL; 564 504 frame->skb_std = skb; 565 505 566 - if (port->type != HSR_PT_MASTER) { 506 + if (port->type != HSR_PT_MASTER) 567 507 frame->is_from_san = true; 568 - } else { 569 - /* Sequence nr for the master node */ 508 + 509 + if (port->type == HSR_PT_MASTER || 510 + port->type == HSR_PT_INTERLINK) { 511 + /* Sequence nr for the master/interlink node */ 570 512 lockdep_assert_held(&hsr->seqnr_lock); 571 513 frame->sequence_nr = hsr->sequence_nr; 572 514 hsr->sequence_nr++; ··· 626 564 { 627 565 struct hsr_priv *hsr = port->hsr; 628 566 struct hsr_vlan_ethhdr *vlan_hdr; 567 + struct list_head *n_db; 629 568 struct ethhdr *ethhdr; 630 569 __be16 proto; 631 570 int ret; ··· 637 574 638 575 memset(frame, 0, sizeof(*frame)); 639 576 frame->is_supervision = is_supervision_frame(port->hsr, skb); 640 - frame->node_src = hsr_get_node(port, &hsr->node_db, skb, 641 - frame->is_supervision, 642 - port->type); 577 + 578 + n_db = &hsr->node_db; 579 + if (port->type == HSR_PT_INTERLINK) 580 + n_db = &hsr->proxy_node_db; 581 + 582 + frame->node_src = hsr_get_node(port, n_db, skb, 583 + frame->is_supervision, port->type); 643 584 if (!frame->node_src) 644 585 return -1; /* Unknown node and !is_supervision, or no mem */ 645 586
+52
net/hsr/hsr_framereg.c
··· 71 71 return NULL; 72 72 } 73 73 74 + /* Check if node for a given MAC address is already present in data base 75 + */ 76 + bool hsr_is_node_in_db(struct list_head *node_db, 77 + const unsigned char addr[ETH_ALEN]) 78 + { 79 + return !!find_node_by_addr_A(node_db, addr); 80 + } 81 + 74 82 /* Helper for device init; the self_node is used in hsr_rcv() to recognize 75 83 * frames from self that's been looped over the HSR ring. 76 84 */ ··· 225 217 return node; 226 218 } 227 219 if (ether_addr_equal(node->macaddress_B, ethhdr->h_source)) { 220 + if (hsr->proto_ops->update_san_info) 221 + hsr->proto_ops->update_san_info(node, is_sup); 222 + return node; 223 + } 224 + } 225 + 226 + /* Check if required node is not in proxy nodes table */ 227 + list_for_each_entry_rcu(node, &hsr->proxy_node_db, mac_list) { 228 + if (ether_addr_equal(node->macaddress_A, ethhdr->h_source)) { 228 229 if (hsr->proto_ops->update_san_info) 229 230 hsr->proto_ops->update_san_info(node, is_sup); 230 231 return node; ··· 435 418 436 419 node_dst = find_node_by_addr_A(&port->hsr->node_db, 437 420 eth_hdr(skb)->h_dest); 421 + if (!node_dst && port->hsr->redbox) 422 + node_dst = find_node_by_addr_A(&port->hsr->proxy_node_db, 423 + eth_hdr(skb)->h_dest); 424 + 438 425 if (!node_dst) { 439 426 if (port->hsr->prot_version != PRP_V1 && net_ratelimit()) 440 427 netdev_err(skb->dev, "%s: Unknown node\n", __func__); ··· 580 559 /* Restart timer */ 581 560 mod_timer(&hsr->prune_timer, 582 561 jiffies + msecs_to_jiffies(PRUNE_PERIOD)); 562 + } 563 + 564 + void hsr_prune_proxy_nodes(struct timer_list *t) 565 + { 566 + struct hsr_priv *hsr = from_timer(hsr, t, prune_proxy_timer); 567 + unsigned long timestamp; 568 + struct hsr_node *node; 569 + struct hsr_node *tmp; 570 + 571 + spin_lock_bh(&hsr->list_lock); 572 + list_for_each_entry_safe(node, tmp, &hsr->proxy_node_db, mac_list) { 573 + timestamp = node->time_in[HSR_PT_INTERLINK]; 574 + 575 + /* Prune old entries */ 576 + if (time_is_before_jiffies(timestamp + 577 + msecs_to_jiffies(HSR_PROXY_NODE_FORGET_TIME))) { 578 + hsr_nl_nodedown(hsr, node->macaddress_A); 579 + if (!node->removed) { 580 + list_del_rcu(&node->mac_list); 581 + node->removed = true; 582 + /* Note that we need to free this entry later: */ 583 + kfree_rcu(node, rcu_head); 584 + } 585 + } 586 + } 587 + 588 + spin_unlock_bh(&hsr->list_lock); 589 + 590 + /* Restart timer */ 591 + mod_timer(&hsr->prune_proxy_timer, 592 + jiffies + msecs_to_jiffies(PRUNE_PROXY_PERIOD)); 583 593 } 584 594 585 595 void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos,
+4
net/hsr/hsr_framereg.h
··· 46 46 u16 sequence_nr); 47 47 48 48 void hsr_prune_nodes(struct timer_list *t); 49 + void hsr_prune_proxy_nodes(struct timer_list *t); 49 50 50 51 int hsr_create_self_node(struct hsr_priv *hsr, 51 52 const unsigned char addr_a[ETH_ALEN], ··· 67 66 void prp_handle_san_frame(bool san, enum hsr_port_type port, 68 67 struct hsr_node *node); 69 68 void prp_update_san_info(struct hsr_node *node, bool is_sup); 69 + 70 + bool hsr_is_node_in_db(struct list_head *node_db, 71 + const unsigned char addr[ETH_ALEN]); 70 72 71 73 struct hsr_node { 72 74 struct list_head mac_list;
+7
net/hsr/hsr_main.h
··· 21 21 */ 22 22 #define HSR_LIFE_CHECK_INTERVAL 2000 /* ms */ 23 23 #define HSR_NODE_FORGET_TIME 60000 /* ms */ 24 + #define HSR_PROXY_NODE_FORGET_TIME 60000 /* ms */ 24 25 #define HSR_ANNOUNCE_INTERVAL 100 /* ms */ 25 26 #define HSR_ENTRY_FORGET_TIME 400 /* ms */ 26 27 ··· 36 35 * HSR_NODE_FORGET_TIME? 37 36 */ 38 37 #define PRUNE_PERIOD 3000 /* ms */ 38 + #define PRUNE_PROXY_PERIOD 3000 /* ms */ 39 39 #define HSR_TLV_EOT 0 /* End of TLVs */ 40 40 #define HSR_TLV_ANNOUNCE 22 41 41 #define HSR_TLV_LIFE_CHECK 23 ··· 194 192 struct rcu_head rcu_head; 195 193 struct list_head ports; 196 194 struct list_head node_db; /* Known HSR nodes */ 195 + struct list_head proxy_node_db; /* RedBox HSR proxy nodes */ 197 196 struct hsr_self_node __rcu *self_node; /* MACs of slaves */ 198 197 struct timer_list announce_timer; /* Supervision frame dispatch */ 199 198 struct timer_list prune_timer; 199 + struct timer_list prune_proxy_timer; 200 200 int announce_count; 201 201 u16 sequence_nr; 202 + u16 interlink_sequence_nr; /* Interlink port seq_nr */ 202 203 u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ 203 204 enum hsr_version prot_version; /* Indicate if HSRv0, HSRv1 or PRPv1 */ 204 205 spinlock_t seqnr_lock; /* locking for sequence_nr */ ··· 214 209 * of lan_id 215 210 */ 216 211 bool fwd_offloaded; /* Forwarding offloaded to HW */ 212 + bool redbox; /* Device supports HSR RedBox */ 213 + unsigned char macaddress_redbox[ETH_ALEN]; 217 214 unsigned char sup_multicast_addr[ETH_ALEN] __aligned(sizeof(u16)); 218 215 /* Align to u16 boundary to avoid unaligned access 219 216 * in ether_addr_equal
+27 -3
net/hsr/hsr_netlink.c
··· 23 23 [IFLA_HSR_SUPERVISION_ADDR] = { .len = ETH_ALEN }, 24 24 [IFLA_HSR_SEQ_NR] = { .type = NLA_U16 }, 25 25 [IFLA_HSR_PROTOCOL] = { .type = NLA_U8 }, 26 + [IFLA_HSR_INTERLINK] = { .type = NLA_U32 }, 26 27 }; 27 28 28 29 /* Here, it seems a netdevice has already been allocated for us, and the ··· 36 35 enum hsr_version proto_version; 37 36 unsigned char multicast_spec; 38 37 u8 proto = HSR_PROTOCOL_HSR; 39 - struct net_device *link[2]; 40 38 39 + struct net_device *link[2], *interlink = NULL; 41 40 if (!data) { 42 41 NL_SET_ERR_MSG_MOD(extack, "No slave devices specified"); 43 42 return -EINVAL; ··· 65 64 66 65 if (link[0] == link[1]) { 67 66 NL_SET_ERR_MSG_MOD(extack, "Slave1 and Slave2 are same"); 67 + return -EINVAL; 68 + } 69 + 70 + if (data[IFLA_HSR_INTERLINK]) 71 + interlink = __dev_get_by_index(src_net, 72 + nla_get_u32(data[IFLA_HSR_INTERLINK])); 73 + 74 + if (interlink && interlink == link[0]) { 75 + NL_SET_ERR_MSG_MOD(extack, "Interlink and Slave1 are the same"); 76 + return -EINVAL; 77 + } 78 + 79 + if (interlink && interlink == link[1]) { 80 + NL_SET_ERR_MSG_MOD(extack, "Interlink and Slave2 are the same"); 68 81 return -EINVAL; 69 82 } 70 83 ··· 111 96 } 112 97 } 113 98 114 - if (proto == HSR_PROTOCOL_PRP) 99 + if (proto == HSR_PROTOCOL_PRP) { 115 100 proto_version = PRP_V1; 101 + if (interlink) { 102 + NL_SET_ERR_MSG_MOD(extack, 103 + "Interlink only works with HSR"); 104 + return -EINVAL; 105 + } 106 + } 116 107 117 - return hsr_dev_finalize(dev, link, multicast_spec, proto_version, extack); 108 + return hsr_dev_finalize(dev, link, interlink, multicast_spec, 109 + proto_version, extack); 118 110 } 119 111 120 112 static void hsr_dellink(struct net_device *dev, struct list_head *head) ··· 129 107 struct hsr_priv *hsr = netdev_priv(dev); 130 108 131 109 del_timer_sync(&hsr->prune_timer); 110 + del_timer_sync(&hsr->prune_proxy_timer); 132 111 del_timer_sync(&hsr->announce_timer); 133 112 134 113 hsr_debugfs_term(hsr); ··· 137 114 138 115 hsr_del_self_node(hsr); 139 116 hsr_del_nodes(&hsr->node_db); 117 + hsr_del_nodes(&hsr->proxy_node_db); 140 118 141 119 unregister_netdevice_queue(dev, head); 142 120 }
+1
net/hsr/hsr_slave.c
··· 55 55 protocol = eth_hdr(skb)->h_proto; 56 56 57 57 if (!(port->dev->features & NETIF_F_HW_HSR_TAG_RM) && 58 + port->type != HSR_PT_INTERLINK && 58 59 hsr->proto_ops->invalid_dan_ingress_frame && 59 60 hsr->proto_ops->invalid_dan_ingress_frame(protocol)) 60 61 goto finish_pass;
+2 -1
tools/testing/selftests/net/hsr/Makefile
··· 2 2 3 3 top_srcdir = ../../../../.. 4 4 5 - TEST_PROGS := hsr_ping.sh 5 + TEST_PROGS := hsr_ping.sh hsr_redbox.sh 6 + TEST_FILES += hsr_common.sh 6 7 7 8 include ../../lib.mk
+84
tools/testing/selftests/net/hsr/hsr_common.sh
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + # Common code for HSR testing scripts 3 + 4 + source ../lib.sh 5 + ret=0 6 + ksft_skip=4 7 + 8 + # $1: IP address 9 + is_v6() 10 + { 11 + [ -z "${1##*:*}" ] 12 + } 13 + 14 + do_ping() 15 + { 16 + local netns="$1" 17 + local connect_addr="$2" 18 + local ping_args="-q -c 2" 19 + 20 + if is_v6 "${connect_addr}"; then 21 + $ipv6 || return 0 22 + ping_args="${ping_args} -6" 23 + fi 24 + 25 + ip netns exec ${netns} ping ${ping_args} $connect_addr >/dev/null 26 + if [ $? -ne 0 ] ; then 27 + echo "$netns -> $connect_addr connectivity [ FAIL ]" 1>&2 28 + ret=1 29 + return 1 30 + fi 31 + 32 + return 0 33 + } 34 + 35 + do_ping_long() 36 + { 37 + local netns="$1" 38 + local connect_addr="$2" 39 + local ping_args="-q -c 10" 40 + 41 + if is_v6 "${connect_addr}"; then 42 + $ipv6 || return 0 43 + ping_args="${ping_args} -6" 44 + fi 45 + 46 + OUT="$(LANG=C ip netns exec ${netns} ping ${ping_args} $connect_addr | grep received)" 47 + if [ $? -ne 0 ] ; then 48 + echo "$netns -> $connect_addr ping [ FAIL ]" 1>&2 49 + ret=1 50 + return 1 51 + fi 52 + 53 + VAL="$(echo $OUT | cut -d' ' -f1-8)" 54 + SED_VAL="$(echo ${VAL} | sed -r -e 's/([0-9]{2}).*([0-9]{2}).*[[:space:]]([0-9]+%).*/\1 transmitted \2 received \3 loss/')" 55 + if [ "${SED_VAL}" != "10 transmitted 10 received 0% loss" ] 56 + then 57 + echo "$netns -> $connect_addr ping TEST [ FAIL ]" 58 + echo "Expect to send and receive 10 packets and no duplicates." 59 + echo "Full message: ${OUT}." 60 + ret=1 61 + return 1 62 + fi 63 + 64 + return 0 65 + } 66 + 67 + stop_if_error() 68 + { 69 + local msg="$1" 70 + 71 + if [ ${ret} -ne 0 ]; then 72 + echo "FAIL: ${msg}" 1>&2 73 + exit ${ret} 74 + fi 75 + } 76 + 77 + check_prerequisites() 78 + { 79 + ip -Version > /dev/null 2>&1 80 + if [ $? -ne 0 ];then 81 + echo "SKIP: Could not run test without ip tool" 82 + exit $ksft_skip 83 + fi 84 + }
+5 -101
tools/testing/selftests/net/hsr/hsr_ping.sh
··· 1 1 #!/bin/bash 2 2 # SPDX-License-Identifier: GPL-2.0 3 3 4 - ret=0 5 - ksft_skip=4 6 4 ipv6=true 5 + 6 + source ./hsr_common.sh 7 7 8 8 optstring="h4" 9 9 usage() { ··· 26 26 ;; 27 27 esac 28 28 done 29 - 30 - sec=$(date +%s) 31 - rndh=$(printf %x $sec)-$(mktemp -u XXXXXX) 32 - ns1="ns1-$rndh" 33 - ns2="ns2-$rndh" 34 - ns3="ns3-$rndh" 35 - 36 - cleanup() 37 - { 38 - local netns 39 - for netns in "$ns1" "$ns2" "$ns3" ;do 40 - ip netns del $netns 41 - done 42 - } 43 - 44 - # $1: IP address 45 - is_v6() 46 - { 47 - [ -z "${1##*:*}" ] 48 - } 49 - 50 - do_ping() 51 - { 52 - local netns="$1" 53 - local connect_addr="$2" 54 - local ping_args="-q -c 2" 55 - 56 - if is_v6 "${connect_addr}"; then 57 - $ipv6 || return 0 58 - ping_args="${ping_args} -6" 59 - fi 60 - 61 - ip netns exec ${netns} ping ${ping_args} $connect_addr >/dev/null 62 - if [ $? -ne 0 ] ; then 63 - echo "$netns -> $connect_addr connectivity [ FAIL ]" 1>&2 64 - ret=1 65 - return 1 66 - fi 67 - 68 - return 0 69 - } 70 - 71 - do_ping_long() 72 - { 73 - local netns="$1" 74 - local connect_addr="$2" 75 - local ping_args="-q -c 10" 76 - 77 - if is_v6 "${connect_addr}"; then 78 - $ipv6 || return 0 79 - ping_args="${ping_args} -6" 80 - fi 81 - 82 - OUT="$(LANG=C ip netns exec ${netns} ping ${ping_args} $connect_addr | grep received)" 83 - if [ $? -ne 0 ] ; then 84 - echo "$netns -> $connect_addr ping [ FAIL ]" 1>&2 85 - ret=1 86 - return 1 87 - fi 88 - 89 - VAL="$(echo $OUT | cut -d' ' -f1-8)" 90 - if [ "$VAL" != "10 packets transmitted, 10 received, 0% packet loss," ] 91 - then 92 - echo "$netns -> $connect_addr ping TEST [ FAIL ]" 93 - echo "Expect to send and receive 10 packets and no duplicates." 94 - echo "Full message: ${OUT}." 95 - ret=1 96 - return 1 97 - fi 98 - 99 - return 0 100 - } 101 - 102 - stop_if_error() 103 - { 104 - local msg="$1" 105 - 106 - if [ ${ret} -ne 0 ]; then 107 - echo "FAIL: ${msg}" 1>&2 108 - exit ${ret} 109 - fi 110 - } 111 29 112 30 do_complete_ping_test() 113 31 { ··· 166 248 ip -net "$ns3" link set hsr3 up 167 249 } 168 250 169 - ip -Version > /dev/null 2>&1 170 - if [ $? -ne 0 ];then 171 - echo "SKIP: Could not run test without ip tool" 172 - exit $ksft_skip 173 - fi 251 + check_prerequisites 252 + setup_ns ns1 ns2 ns3 174 253 175 - trap cleanup EXIT 176 - 177 - for i in "$ns1" "$ns2" "$ns3" ;do 178 - ip netns add $i || exit $ksft_skip 179 - ip -net $i link set lo up 180 - done 254 + trap cleanup_all_ns EXIT 181 255 182 256 setup_hsr_interfaces 0 183 257 do_complete_ping_test 184 - cleanup 185 - 186 - for i in "$ns1" "$ns2" "$ns3" ;do 187 - ip netns add $i || exit $ksft_skip 188 - ip -net $i link set lo up 189 - done 190 258 191 259 setup_hsr_interfaces 1 192 260 do_complete_ping_test
+92
tools/testing/selftests/net/hsr/hsr_redbox.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + 4 + ipv6=false 5 + 6 + source ./hsr_common.sh 7 + 8 + do_complete_ping_test() 9 + { 10 + echo "INFO: Initial validation ping (HSR-SAN/RedBox)." 11 + # Each node has to be able each one. 12 + do_ping "${ns1}" 100.64.0.2 13 + do_ping "${ns2}" 100.64.0.1 14 + # Ping from SAN to hsr1 (via hsr2) 15 + do_ping "${ns3}" 100.64.0.1 16 + do_ping "${ns1}" 100.64.0.3 17 + stop_if_error "Initial validation failed." 18 + 19 + # Wait for MGNT HSR frames being received and nodes being 20 + # merged. 21 + sleep 5 22 + 23 + echo "INFO: Longer ping test (HSR-SAN/RedBox)." 24 + # Ping from SAN to hsr1 (via hsr2) 25 + do_ping_long "${ns3}" 100.64.0.1 26 + # Ping from hsr1 (via hsr2) to SAN 27 + do_ping_long "${ns1}" 100.64.0.3 28 + stop_if_error "Longer ping test failed." 29 + 30 + echo "INFO: All good." 31 + } 32 + 33 + setup_hsr_interfaces() 34 + { 35 + local HSRv="$1" 36 + 37 + echo "INFO: preparing interfaces for HSRv${HSRv} (HSR-SAN/RedBox)." 38 + 39 + # |NS1 | 40 + # | | 41 + # | /-- hsr1 --\ | 42 + # | ns1eth1 ns1eth2 | 43 + # |------------------------| 44 + # | | 45 + # | | 46 + # | | 47 + # |------------------------| |-----------| 48 + # | ns2eth1 ns2eth2 | | | 49 + # | \-- hsr2 --/ | | | 50 + # | \ | | | 51 + # | ns2eth3 |--------| ns3eth1 | 52 + # | (interlink)| | | 53 + # |NS2 (RedBOX) | |NS3 (SAN) | 54 + # 55 + # Check if iproute2 supports adding interlink port to hsrX device 56 + ip link help hsr | grep -q INTERLINK 57 + [ $? -ne 0 ] && { echo "iproute2: HSR interlink interface not supported!"; exit 0; } 58 + 59 + # Create interfaces for name spaces 60 + ip link add ns1eth1 netns "${ns1}" type veth peer name ns2eth1 netns "${ns2}" 61 + ip link add ns1eth2 netns "${ns1}" type veth peer name ns2eth2 netns "${ns2}" 62 + ip link add ns3eth1 netns "${ns3}" type veth peer name ns2eth3 netns "${ns2}" 63 + 64 + sleep 1 65 + 66 + ip -n "${ns1}" link set ns1eth1 up 67 + ip -n "${ns1}" link set ns1eth2 up 68 + 69 + ip -n "${ns2}" link set ns2eth1 up 70 + ip -n "${ns2}" link set ns2eth2 up 71 + ip -n "${ns2}" link set ns2eth3 up 72 + 73 + ip -n "${ns3}" link set ns3eth1 up 74 + 75 + ip -net "${ns1}" link add name hsr1 type hsr slave1 ns1eth1 slave2 ns1eth2 supervision 45 version ${HSRv} proto 0 76 + ip -net "${ns2}" link add name hsr2 type hsr slave1 ns2eth1 slave2 ns2eth2 interlink ns2eth3 supervision 45 version ${HSRv} proto 0 77 + 78 + ip -n "${ns1}" addr add 100.64.0.1/24 dev hsr1 79 + ip -n "${ns2}" addr add 100.64.0.2/24 dev hsr2 80 + ip -n "${ns3}" addr add 100.64.0.3/24 dev ns3eth1 81 + 82 + ip -n "${ns1}" link set hsr1 up 83 + ip -n "${ns2}" link set hsr2 up 84 + } 85 + 86 + check_prerequisites 87 + setup_ns ns1 ns2 ns3 88 + 89 + setup_hsr_interfaces 1 90 + do_complete_ping_test 91 + 92 + exit $ret