18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* Copyright 2011-2014 Autronica Fire and Security AS 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Author(s): 58c2ecf20Sopenharmony_ci * 2011-2014 Arvid Brodin, arvid.brodin@alten.se 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * include file for HSR and PRP. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef __HSR_PRIVATE_H 118c2ecf20Sopenharmony_ci#define __HSR_PRIVATE_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 148c2ecf20Sopenharmony_ci#include <linux/list.h> 158c2ecf20Sopenharmony_ci#include <linux/if_vlan.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Time constants as specified in the HSR specification (IEC-62439-3 2010) 188c2ecf20Sopenharmony_ci * Table 8. 198c2ecf20Sopenharmony_ci * All values in milliseconds. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci#define HSR_LIFE_CHECK_INTERVAL 2000 /* ms */ 228c2ecf20Sopenharmony_ci#define HSR_NODE_FORGET_TIME 60000 /* ms */ 238c2ecf20Sopenharmony_ci#define HSR_ANNOUNCE_INTERVAL 100 /* ms */ 248c2ecf20Sopenharmony_ci#define HSR_ENTRY_FORGET_TIME 400 /* ms */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* By how much may slave1 and slave2 timestamps of latest received frame from 278c2ecf20Sopenharmony_ci * each node differ before we notify of communication problem? 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci#define MAX_SLAVE_DIFF 3000 /* ms */ 308c2ecf20Sopenharmony_ci#define HSR_SEQNR_START (USHRT_MAX - 1024) 318c2ecf20Sopenharmony_ci#define HSR_SUP_SEQNR_START (HSR_SEQNR_START / 2) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* How often shall we check for broken ring and remove node entries older than 348c2ecf20Sopenharmony_ci * HSR_NODE_FORGET_TIME? 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci#define PRUNE_PERIOD 3000 /* ms */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define HSR_TLV_ANNOUNCE 22 398c2ecf20Sopenharmony_ci#define HSR_TLV_LIFE_CHECK 23 408c2ecf20Sopenharmony_ci/* PRP V1 life check for Duplicate discard */ 418c2ecf20Sopenharmony_ci#define PRP_TLV_LIFE_CHECK_DD 20 428c2ecf20Sopenharmony_ci/* PRP V1 life check for Duplicate Accept */ 438c2ecf20Sopenharmony_ci#define PRP_TLV_LIFE_CHECK_DA 21 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* HSR Tag. 468c2ecf20Sopenharmony_ci * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB, 478c2ecf20Sopenharmony_ci * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest, 488c2ecf20Sopenharmony_ci * h_source, h_proto = 0x88FB }, and add { path, LSDU_size, sequence Nr, 498c2ecf20Sopenharmony_ci * encapsulated protocol } instead. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * Field names as defined in the IEC:2010 standard for HSR. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_cistruct hsr_tag { 548c2ecf20Sopenharmony_ci __be16 path_and_LSDU_size; 558c2ecf20Sopenharmony_ci __be16 sequence_nr; 568c2ecf20Sopenharmony_ci __be16 encap_proto; 578c2ecf20Sopenharmony_ci} __packed; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define HSR_HLEN 6 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define HSR_V1_SUP_LSDUSIZE 52 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* The helper functions below assumes that 'path' occupies the 4 most 648c2ecf20Sopenharmony_ci * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or 658c2ecf20Sopenharmony_ci * equivalently, the 4 most significant bits of HSR tag byte 14). 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci * This is unclear in the IEC specification; its definition of MAC addresses 688c2ecf20Sopenharmony_ci * indicates the spec is written with the least significant bit first (to the 698c2ecf20Sopenharmony_ci * left). This, however, would mean that the LSDU field would be split in two 708c2ecf20Sopenharmony_ci * with the path field in-between, which seems strange. I'm guessing the MAC 718c2ecf20Sopenharmony_ci * address definition is in error. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic inline void set_hsr_tag_path(struct hsr_tag *ht, u16 path) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci ht->path_and_LSDU_size = 778c2ecf20Sopenharmony_ci htons((ntohs(ht->path_and_LSDU_size) & 0x0FFF) | (path << 12)); 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic inline void set_hsr_tag_LSDU_size(struct hsr_tag *ht, u16 LSDU_size) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci ht->path_and_LSDU_size = htons((ntohs(ht->path_and_LSDU_size) & 838c2ecf20Sopenharmony_ci 0xF000) | (LSDU_size & 0x0FFF)); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistruct hsr_ethhdr { 878c2ecf20Sopenharmony_ci struct ethhdr ethhdr; 888c2ecf20Sopenharmony_ci struct hsr_tag hsr_tag; 898c2ecf20Sopenharmony_ci} __packed; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct hsr_vlan_ethhdr { 928c2ecf20Sopenharmony_ci struct vlan_ethhdr vlanhdr; 938c2ecf20Sopenharmony_ci struct hsr_tag hsr_tag; 948c2ecf20Sopenharmony_ci} __packed; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/* HSR/PRP Supervision Frame data types. 978c2ecf20Sopenharmony_ci * Field names as defined in the IEC:2010 standard for HSR. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_cistruct hsr_sup_tag { 1008c2ecf20Sopenharmony_ci __be16 path_and_HSR_ver; 1018c2ecf20Sopenharmony_ci __be16 sequence_nr; 1028c2ecf20Sopenharmony_ci __u8 HSR_TLV_type; 1038c2ecf20Sopenharmony_ci __u8 HSR_TLV_length; 1048c2ecf20Sopenharmony_ci} __packed; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistruct hsr_sup_payload { 1078c2ecf20Sopenharmony_ci unsigned char macaddress_A[ETH_ALEN]; 1088c2ecf20Sopenharmony_ci} __packed; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic inline void set_hsr_stag_path(struct hsr_sup_tag *hst, u16 path) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci set_hsr_tag_path((struct hsr_tag *)hst, path); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic inline void set_hsr_stag_HSR_ver(struct hsr_sup_tag *hst, u16 HSR_ver) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci set_hsr_tag_LSDU_size((struct hsr_tag *)hst, HSR_ver); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistruct hsrv0_ethhdr_sp { 1218c2ecf20Sopenharmony_ci struct ethhdr ethhdr; 1228c2ecf20Sopenharmony_ci struct hsr_sup_tag hsr_sup; 1238c2ecf20Sopenharmony_ci} __packed; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistruct hsrv1_ethhdr_sp { 1268c2ecf20Sopenharmony_ci struct ethhdr ethhdr; 1278c2ecf20Sopenharmony_ci struct hsr_tag hsr; 1288c2ecf20Sopenharmony_ci struct hsr_sup_tag hsr_sup; 1298c2ecf20Sopenharmony_ci} __packed; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cienum hsr_port_type { 1328c2ecf20Sopenharmony_ci HSR_PT_NONE = 0, /* Must be 0, used by framereg */ 1338c2ecf20Sopenharmony_ci HSR_PT_SLAVE_A, 1348c2ecf20Sopenharmony_ci HSR_PT_SLAVE_B, 1358c2ecf20Sopenharmony_ci HSR_PT_INTERLINK, 1368c2ecf20Sopenharmony_ci HSR_PT_MASTER, 1378c2ecf20Sopenharmony_ci HSR_PT_PORTS, /* This must be the last item in the enum */ 1388c2ecf20Sopenharmony_ci}; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci/* PRP Redunancy Control Trailor (RCT). 1418c2ecf20Sopenharmony_ci * As defined in IEC-62439-4:2012, the PRP RCT is really { sequence Nr, 1428c2ecf20Sopenharmony_ci * Lan indentifier (LanId), LSDU_size and PRP_suffix = 0x88FB }. 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * Field names as defined in the IEC:2012 standard for PRP. 1458c2ecf20Sopenharmony_ci */ 1468c2ecf20Sopenharmony_cistruct prp_rct { 1478c2ecf20Sopenharmony_ci __be16 sequence_nr; 1488c2ecf20Sopenharmony_ci __be16 lan_id_and_LSDU_size; 1498c2ecf20Sopenharmony_ci __be16 PRP_suffix; 1508c2ecf20Sopenharmony_ci} __packed; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic inline u16 get_prp_LSDU_size(struct prp_rct *rct) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci return ntohs(rct->lan_id_and_LSDU_size) & 0x0FFF; 1558c2ecf20Sopenharmony_ci} 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic inline void set_prp_lan_id(struct prp_rct *rct, u16 lan_id) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci rct->lan_id_and_LSDU_size = htons((ntohs(rct->lan_id_and_LSDU_size) & 1608c2ecf20Sopenharmony_ci 0x0FFF) | (lan_id << 12)); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_cistatic inline void set_prp_LSDU_size(struct prp_rct *rct, u16 LSDU_size) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci rct->lan_id_and_LSDU_size = htons((ntohs(rct->lan_id_and_LSDU_size) & 1658c2ecf20Sopenharmony_ci 0xF000) | (LSDU_size & 0x0FFF)); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistruct hsr_port { 1698c2ecf20Sopenharmony_ci struct list_head port_list; 1708c2ecf20Sopenharmony_ci struct net_device *dev; 1718c2ecf20Sopenharmony_ci struct hsr_priv *hsr; 1728c2ecf20Sopenharmony_ci enum hsr_port_type type; 1738c2ecf20Sopenharmony_ci}; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* used by driver internally to differentiate various protocols */ 1768c2ecf20Sopenharmony_cienum hsr_version { 1778c2ecf20Sopenharmony_ci HSR_V0 = 0, 1788c2ecf20Sopenharmony_ci HSR_V1, 1798c2ecf20Sopenharmony_ci PRP_V1, 1808c2ecf20Sopenharmony_ci}; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistruct hsr_frame_info; 1838c2ecf20Sopenharmony_cistruct hsr_node; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistruct hsr_proto_ops { 1868c2ecf20Sopenharmony_ci /* format and send supervision frame */ 1878c2ecf20Sopenharmony_ci void (*send_sv_frame)(struct hsr_port *port, unsigned long *interval); 1888c2ecf20Sopenharmony_ci void (*handle_san_frame)(bool san, enum hsr_port_type port, 1898c2ecf20Sopenharmony_ci struct hsr_node *node); 1908c2ecf20Sopenharmony_ci bool (*drop_frame)(struct hsr_frame_info *frame, struct hsr_port *port); 1918c2ecf20Sopenharmony_ci struct sk_buff * (*get_untagged_frame)(struct hsr_frame_info *frame, 1928c2ecf20Sopenharmony_ci struct hsr_port *port); 1938c2ecf20Sopenharmony_ci struct sk_buff * (*create_tagged_frame)(struct hsr_frame_info *frame, 1948c2ecf20Sopenharmony_ci struct hsr_port *port); 1958c2ecf20Sopenharmony_ci int (*fill_frame_info)(__be16 proto, struct sk_buff *skb, 1968c2ecf20Sopenharmony_ci struct hsr_frame_info *frame); 1978c2ecf20Sopenharmony_ci bool (*invalid_dan_ingress_frame)(__be16 protocol); 1988c2ecf20Sopenharmony_ci void (*update_san_info)(struct hsr_node *node, bool is_sup); 1998c2ecf20Sopenharmony_ci}; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistruct hsr_priv { 2028c2ecf20Sopenharmony_ci struct rcu_head rcu_head; 2038c2ecf20Sopenharmony_ci struct list_head ports; 2048c2ecf20Sopenharmony_ci struct list_head node_db; /* Known HSR nodes */ 2058c2ecf20Sopenharmony_ci struct list_head self_node_db; /* MACs of slaves */ 2068c2ecf20Sopenharmony_ci struct timer_list announce_timer; /* Supervision frame dispatch */ 2078c2ecf20Sopenharmony_ci struct timer_list prune_timer; 2088c2ecf20Sopenharmony_ci int announce_count; 2098c2ecf20Sopenharmony_ci u16 sequence_nr; 2108c2ecf20Sopenharmony_ci u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ 2118c2ecf20Sopenharmony_ci enum hsr_version prot_version; /* Indicate if HSRv0, HSRv1 or PRPv1 */ 2128c2ecf20Sopenharmony_ci spinlock_t seqnr_lock; /* locking for sequence_nr */ 2138c2ecf20Sopenharmony_ci spinlock_t list_lock; /* locking for node list */ 2148c2ecf20Sopenharmony_ci struct hsr_proto_ops *proto_ops; 2158c2ecf20Sopenharmony_ci#define PRP_LAN_ID 0x5 /* 0x1010 for A and 0x1011 for B. Bit 0 is set 2168c2ecf20Sopenharmony_ci * based on SLAVE_A or SLAVE_B 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci u8 net_id; /* for PRP, it occupies most significant 3 bits 2198c2ecf20Sopenharmony_ci * of lan_id 2208c2ecf20Sopenharmony_ci */ 2218c2ecf20Sopenharmony_ci unsigned char sup_multicast_addr[ETH_ALEN]; 2228c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 2238c2ecf20Sopenharmony_ci struct dentry *node_tbl_root; 2248c2ecf20Sopenharmony_ci#endif 2258c2ecf20Sopenharmony_ci}; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci#define hsr_for_each_port(hsr, port) \ 2288c2ecf20Sopenharmony_ci list_for_each_entry_rcu((port), &(hsr)->ports, port_list) 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistruct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/* Caller must ensure skb is a valid HSR frame */ 2338c2ecf20Sopenharmony_cistatic inline u16 hsr_get_skb_sequence_nr(struct sk_buff *skb) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci struct hsr_ethhdr *hsr_ethhdr; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb); 2388c2ecf20Sopenharmony_ci return ntohs(hsr_ethhdr->hsr_tag.sequence_nr); 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic inline struct prp_rct *skb_get_PRP_rct(struct sk_buff *skb) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci unsigned char *tail = skb_tail_pointer(skb) - HSR_HLEN; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci struct prp_rct *rct = (struct prp_rct *)tail; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci if (rct->PRP_suffix == htons(ETH_P_PRP)) 2488c2ecf20Sopenharmony_ci return rct; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci return NULL; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci/* Assume caller has confirmed this skb is PRP suffixed */ 2548c2ecf20Sopenharmony_cistatic inline u16 prp_get_skb_sequence_nr(struct prp_rct *rct) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci return ntohs(rct->sequence_nr); 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic inline u16 get_prp_lan_id(struct prp_rct *rct) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci return ntohs(rct->lan_id_and_LSDU_size) >> 12; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/* assume there is a valid rct */ 2658c2ecf20Sopenharmony_cistatic inline bool prp_check_lsdu_size(struct sk_buff *skb, 2668c2ecf20Sopenharmony_ci struct prp_rct *rct, 2678c2ecf20Sopenharmony_ci bool is_sup) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci struct ethhdr *ethhdr; 2708c2ecf20Sopenharmony_ci int expected_lsdu_size; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (is_sup) { 2738c2ecf20Sopenharmony_ci expected_lsdu_size = HSR_V1_SUP_LSDUSIZE; 2748c2ecf20Sopenharmony_ci } else { 2758c2ecf20Sopenharmony_ci ethhdr = (struct ethhdr *)skb_mac_header(skb); 2768c2ecf20Sopenharmony_ci expected_lsdu_size = skb->len - 14; 2778c2ecf20Sopenharmony_ci if (ethhdr->h_proto == htons(ETH_P_8021Q)) 2788c2ecf20Sopenharmony_ci expected_lsdu_size -= 4; 2798c2ecf20Sopenharmony_ci } 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci return (expected_lsdu_size == get_prp_LSDU_size(rct)); 2828c2ecf20Sopenharmony_ci} 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DEBUG_FS) 2858c2ecf20Sopenharmony_civoid hsr_debugfs_rename(struct net_device *dev); 2868c2ecf20Sopenharmony_civoid hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev); 2878c2ecf20Sopenharmony_civoid hsr_debugfs_term(struct hsr_priv *priv); 2888c2ecf20Sopenharmony_civoid hsr_debugfs_create_root(void); 2898c2ecf20Sopenharmony_civoid hsr_debugfs_remove_root(void); 2908c2ecf20Sopenharmony_ci#else 2918c2ecf20Sopenharmony_cistatic inline void hsr_debugfs_rename(struct net_device *dev) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci} 2948c2ecf20Sopenharmony_cistatic inline void hsr_debugfs_init(struct hsr_priv *priv, 2958c2ecf20Sopenharmony_ci struct net_device *hsr_dev) 2968c2ecf20Sopenharmony_ci{} 2978c2ecf20Sopenharmony_cistatic inline void hsr_debugfs_term(struct hsr_priv *priv) 2988c2ecf20Sopenharmony_ci{} 2998c2ecf20Sopenharmony_cistatic inline void hsr_debugfs_create_root(void) 3008c2ecf20Sopenharmony_ci{} 3018c2ecf20Sopenharmony_cistatic inline void hsr_debugfs_remove_root(void) 3028c2ecf20Sopenharmony_ci{} 3038c2ecf20Sopenharmony_ci#endif 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci#endif /* __HSR_PRIVATE_H */ 306