.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
---|
1 | 2 | /* Copyright 2011-2014 Autronica Fire and Security AS |
---|
2 | | - * |
---|
3 | | - * This program is free software; you can redistribute it and/or modify it |
---|
4 | | - * under the terms of the GNU General Public License as published by the Free |
---|
5 | | - * Software Foundation; either version 2 of the License, or (at your option) |
---|
6 | | - * any later version. |
---|
7 | 3 | * |
---|
8 | 4 | * Author(s): |
---|
9 | 5 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
---|
| 6 | + * |
---|
| 7 | + * include file for HSR and PRP. |
---|
10 | 8 | */ |
---|
11 | 9 | |
---|
12 | 10 | #ifndef __HSR_PRIVATE_H |
---|
.. | .. |
---|
14 | 12 | |
---|
15 | 13 | #include <linux/netdevice.h> |
---|
16 | 14 | #include <linux/list.h> |
---|
17 | | - |
---|
| 15 | +#include <linux/if_vlan.h> |
---|
18 | 16 | |
---|
19 | 17 | /* Time constants as specified in the HSR specification (IEC-62439-3 2010) |
---|
20 | 18 | * Table 8. |
---|
.. | .. |
---|
23 | 21 | #define HSR_LIFE_CHECK_INTERVAL 2000 /* ms */ |
---|
24 | 22 | #define HSR_NODE_FORGET_TIME 60000 /* ms */ |
---|
25 | 23 | #define HSR_ANNOUNCE_INTERVAL 100 /* ms */ |
---|
26 | | - |
---|
| 24 | +#define HSR_ENTRY_FORGET_TIME 400 /* ms */ |
---|
27 | 25 | |
---|
28 | 26 | /* By how much may slave1 and slave2 timestamps of latest received frame from |
---|
29 | 27 | * each node differ before we notify of communication problem? |
---|
.. | .. |
---|
32 | 30 | #define HSR_SEQNR_START (USHRT_MAX - 1024) |
---|
33 | 31 | #define HSR_SUP_SEQNR_START (HSR_SEQNR_START / 2) |
---|
34 | 32 | |
---|
35 | | - |
---|
36 | 33 | /* How often shall we check for broken ring and remove node entries older than |
---|
37 | 34 | * HSR_NODE_FORGET_TIME? |
---|
38 | 35 | */ |
---|
39 | 36 | #define PRUNE_PERIOD 3000 /* ms */ |
---|
40 | 37 | |
---|
41 | | - |
---|
42 | 38 | #define HSR_TLV_ANNOUNCE 22 |
---|
43 | 39 | #define HSR_TLV_LIFE_CHECK 23 |
---|
44 | | - |
---|
| 40 | +/* PRP V1 life check for Duplicate discard */ |
---|
| 41 | +#define PRP_TLV_LIFE_CHECK_DD 20 |
---|
| 42 | +/* PRP V1 life check for Duplicate Accept */ |
---|
| 43 | +#define PRP_TLV_LIFE_CHECK_DA 21 |
---|
45 | 44 | |
---|
46 | 45 | /* HSR Tag. |
---|
47 | 46 | * As defined in IEC-62439-3:2010, the HSR tag is really { ethertype = 0x88FB, |
---|
.. | .. |
---|
71 | 70 | * with the path field in-between, which seems strange. I'm guessing the MAC |
---|
72 | 71 | * address definition is in error. |
---|
73 | 72 | */ |
---|
74 | | -static inline u16 get_hsr_tag_path(struct hsr_tag *ht) |
---|
75 | | -{ |
---|
76 | | - return ntohs(ht->path_and_LSDU_size) >> 12; |
---|
77 | | -} |
---|
78 | | - |
---|
79 | | -static inline u16 get_hsr_tag_LSDU_size(struct hsr_tag *ht) |
---|
80 | | -{ |
---|
81 | | - return ntohs(ht->path_and_LSDU_size) & 0x0FFF; |
---|
82 | | -} |
---|
83 | 73 | |
---|
84 | 74 | static inline void set_hsr_tag_path(struct hsr_tag *ht, u16 path) |
---|
85 | 75 | { |
---|
86 | | - ht->path_and_LSDU_size = htons( |
---|
87 | | - (ntohs(ht->path_and_LSDU_size) & 0x0FFF) | (path << 12)); |
---|
| 76 | + ht->path_and_LSDU_size = |
---|
| 77 | + htons((ntohs(ht->path_and_LSDU_size) & 0x0FFF) | (path << 12)); |
---|
88 | 78 | } |
---|
89 | 79 | |
---|
90 | 80 | static inline void set_hsr_tag_LSDU_size(struct hsr_tag *ht, u16 LSDU_size) |
---|
91 | 81 | { |
---|
92 | | - ht->path_and_LSDU_size = htons( |
---|
93 | | - (ntohs(ht->path_and_LSDU_size) & 0xF000) | |
---|
94 | | - (LSDU_size & 0x0FFF)); |
---|
| 82 | + ht->path_and_LSDU_size = htons((ntohs(ht->path_and_LSDU_size) & |
---|
| 83 | + 0xF000) | (LSDU_size & 0x0FFF)); |
---|
95 | 84 | } |
---|
96 | 85 | |
---|
97 | 86 | struct hsr_ethhdr { |
---|
.. | .. |
---|
99 | 88 | struct hsr_tag hsr_tag; |
---|
100 | 89 | } __packed; |
---|
101 | 90 | |
---|
| 91 | +struct hsr_vlan_ethhdr { |
---|
| 92 | + struct vlan_ethhdr vlanhdr; |
---|
| 93 | + struct hsr_tag hsr_tag; |
---|
| 94 | +} __packed; |
---|
102 | 95 | |
---|
103 | | -/* HSR Supervision Frame data types. |
---|
| 96 | +/* HSR/PRP Supervision Frame data types. |
---|
104 | 97 | * Field names as defined in the IEC:2010 standard for HSR. |
---|
105 | 98 | */ |
---|
106 | 99 | struct hsr_sup_tag { |
---|
107 | | - __be16 path_and_HSR_Ver; |
---|
| 100 | + __be16 path_and_HSR_ver; |
---|
108 | 101 | __be16 sequence_nr; |
---|
109 | | - __u8 HSR_TLV_Type; |
---|
110 | | - __u8 HSR_TLV_Length; |
---|
| 102 | + __u8 HSR_TLV_type; |
---|
| 103 | + __u8 HSR_TLV_length; |
---|
111 | 104 | } __packed; |
---|
112 | 105 | |
---|
113 | 106 | struct hsr_sup_payload { |
---|
114 | | - unsigned char MacAddressA[ETH_ALEN]; |
---|
| 107 | + unsigned char macaddress_A[ETH_ALEN]; |
---|
115 | 108 | } __packed; |
---|
116 | | - |
---|
117 | | -static inline u16 get_hsr_stag_path(struct hsr_sup_tag *hst) |
---|
118 | | -{ |
---|
119 | | - return get_hsr_tag_path((struct hsr_tag *) hst); |
---|
120 | | -} |
---|
121 | | - |
---|
122 | | -static inline u16 get_hsr_stag_HSR_ver(struct hsr_sup_tag *hst) |
---|
123 | | -{ |
---|
124 | | - return get_hsr_tag_LSDU_size((struct hsr_tag *) hst); |
---|
125 | | -} |
---|
126 | 109 | |
---|
127 | 110 | static inline void set_hsr_stag_path(struct hsr_sup_tag *hst, u16 path) |
---|
128 | 111 | { |
---|
129 | | - set_hsr_tag_path((struct hsr_tag *) hst, path); |
---|
| 112 | + set_hsr_tag_path((struct hsr_tag *)hst, path); |
---|
130 | 113 | } |
---|
131 | 114 | |
---|
132 | | -static inline void set_hsr_stag_HSR_Ver(struct hsr_sup_tag *hst, u16 HSR_Ver) |
---|
| 115 | +static inline void set_hsr_stag_HSR_ver(struct hsr_sup_tag *hst, u16 HSR_ver) |
---|
133 | 116 | { |
---|
134 | | - set_hsr_tag_LSDU_size((struct hsr_tag *) hst, HSR_Ver); |
---|
| 117 | + set_hsr_tag_LSDU_size((struct hsr_tag *)hst, HSR_ver); |
---|
135 | 118 | } |
---|
136 | 119 | |
---|
137 | 120 | struct hsrv0_ethhdr_sp { |
---|
.. | .. |
---|
145 | 128 | struct hsr_sup_tag hsr_sup; |
---|
146 | 129 | } __packed; |
---|
147 | 130 | |
---|
148 | | - |
---|
149 | 131 | enum hsr_port_type { |
---|
150 | 132 | HSR_PT_NONE = 0, /* Must be 0, used by framereg */ |
---|
151 | 133 | HSR_PT_SLAVE_A, |
---|
.. | .. |
---|
155 | 137 | HSR_PT_PORTS, /* This must be the last item in the enum */ |
---|
156 | 138 | }; |
---|
157 | 139 | |
---|
| 140 | +/* PRP Redunancy Control Trailor (RCT). |
---|
| 141 | + * As defined in IEC-62439-4:2012, the PRP RCT is really { sequence Nr, |
---|
| 142 | + * Lan indentifier (LanId), LSDU_size and PRP_suffix = 0x88FB }. |
---|
| 143 | + * |
---|
| 144 | + * Field names as defined in the IEC:2012 standard for PRP. |
---|
| 145 | + */ |
---|
| 146 | +struct prp_rct { |
---|
| 147 | + __be16 sequence_nr; |
---|
| 148 | + __be16 lan_id_and_LSDU_size; |
---|
| 149 | + __be16 PRP_suffix; |
---|
| 150 | +} __packed; |
---|
| 151 | + |
---|
| 152 | +static inline u16 get_prp_LSDU_size(struct prp_rct *rct) |
---|
| 153 | +{ |
---|
| 154 | + return ntohs(rct->lan_id_and_LSDU_size) & 0x0FFF; |
---|
| 155 | +} |
---|
| 156 | + |
---|
| 157 | +static inline void set_prp_lan_id(struct prp_rct *rct, u16 lan_id) |
---|
| 158 | +{ |
---|
| 159 | + rct->lan_id_and_LSDU_size = htons((ntohs(rct->lan_id_and_LSDU_size) & |
---|
| 160 | + 0x0FFF) | (lan_id << 12)); |
---|
| 161 | +} |
---|
| 162 | +static inline void set_prp_LSDU_size(struct prp_rct *rct, u16 LSDU_size) |
---|
| 163 | +{ |
---|
| 164 | + rct->lan_id_and_LSDU_size = htons((ntohs(rct->lan_id_and_LSDU_size) & |
---|
| 165 | + 0xF000) | (LSDU_size & 0x0FFF)); |
---|
| 166 | +} |
---|
| 167 | + |
---|
158 | 168 | struct hsr_port { |
---|
159 | 169 | struct list_head port_list; |
---|
160 | 170 | struct net_device *dev; |
---|
161 | 171 | struct hsr_priv *hsr; |
---|
162 | 172 | enum hsr_port_type type; |
---|
| 173 | +}; |
---|
| 174 | + |
---|
| 175 | +/* used by driver internally to differentiate various protocols */ |
---|
| 176 | +enum hsr_version { |
---|
| 177 | + HSR_V0 = 0, |
---|
| 178 | + HSR_V1, |
---|
| 179 | + PRP_V1, |
---|
| 180 | +}; |
---|
| 181 | + |
---|
| 182 | +struct hsr_frame_info; |
---|
| 183 | +struct hsr_node; |
---|
| 184 | + |
---|
| 185 | +struct hsr_proto_ops { |
---|
| 186 | + /* format and send supervision frame */ |
---|
| 187 | + void (*send_sv_frame)(struct hsr_port *port, unsigned long *interval); |
---|
| 188 | + void (*handle_san_frame)(bool san, enum hsr_port_type port, |
---|
| 189 | + struct hsr_node *node); |
---|
| 190 | + bool (*drop_frame)(struct hsr_frame_info *frame, struct hsr_port *port); |
---|
| 191 | + struct sk_buff * (*get_untagged_frame)(struct hsr_frame_info *frame, |
---|
| 192 | + struct hsr_port *port); |
---|
| 193 | + struct sk_buff * (*create_tagged_frame)(struct hsr_frame_info *frame, |
---|
| 194 | + struct hsr_port *port); |
---|
| 195 | + int (*fill_frame_info)(__be16 proto, struct sk_buff *skb, |
---|
| 196 | + struct hsr_frame_info *frame); |
---|
| 197 | + bool (*invalid_dan_ingress_frame)(__be16 protocol); |
---|
| 198 | + void (*update_san_info)(struct hsr_node *node, bool is_sup); |
---|
163 | 199 | }; |
---|
164 | 200 | |
---|
165 | 201 | struct hsr_priv { |
---|
.. | .. |
---|
171 | 207 | struct timer_list prune_timer; |
---|
172 | 208 | int announce_count; |
---|
173 | 209 | u16 sequence_nr; |
---|
174 | | - u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ |
---|
175 | | - u8 protVersion; /* Indicate if HSRv0 or HSRv1. */ |
---|
176 | | - spinlock_t seqnr_lock; /* locking for sequence_nr */ |
---|
| 210 | + u16 sup_sequence_nr; /* For HSRv1 separate seq_nr for supervision */ |
---|
| 211 | + enum hsr_version prot_version; /* Indicate if HSRv0, HSRv1 or PRPv1 */ |
---|
| 212 | + spinlock_t seqnr_lock; /* locking for sequence_nr */ |
---|
| 213 | + spinlock_t list_lock; /* locking for node list */ |
---|
| 214 | + struct hsr_proto_ops *proto_ops; |
---|
| 215 | +#define PRP_LAN_ID 0x5 /* 0x1010 for A and 0x1011 for B. Bit 0 is set |
---|
| 216 | + * based on SLAVE_A or SLAVE_B |
---|
| 217 | + */ |
---|
| 218 | + u8 net_id; /* for PRP, it occupies most significant 3 bits |
---|
| 219 | + * of lan_id |
---|
| 220 | + */ |
---|
177 | 221 | unsigned char sup_multicast_addr[ETH_ALEN]; |
---|
| 222 | +#ifdef CONFIG_DEBUG_FS |
---|
| 223 | + struct dentry *node_tbl_root; |
---|
| 224 | +#endif |
---|
178 | 225 | }; |
---|
179 | 226 | |
---|
180 | 227 | #define hsr_for_each_port(hsr, port) \ |
---|
.. | .. |
---|
187 | 234 | { |
---|
188 | 235 | struct hsr_ethhdr *hsr_ethhdr; |
---|
189 | 236 | |
---|
190 | | - hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb); |
---|
| 237 | + hsr_ethhdr = (struct hsr_ethhdr *)skb_mac_header(skb); |
---|
191 | 238 | return ntohs(hsr_ethhdr->hsr_tag.sequence_nr); |
---|
192 | 239 | } |
---|
193 | 240 | |
---|
| 241 | +static inline struct prp_rct *skb_get_PRP_rct(struct sk_buff *skb) |
---|
| 242 | +{ |
---|
| 243 | + unsigned char *tail = skb_tail_pointer(skb) - HSR_HLEN; |
---|
| 244 | + |
---|
| 245 | + struct prp_rct *rct = (struct prp_rct *)tail; |
---|
| 246 | + |
---|
| 247 | + if (rct->PRP_suffix == htons(ETH_P_PRP)) |
---|
| 248 | + return rct; |
---|
| 249 | + |
---|
| 250 | + return NULL; |
---|
| 251 | +} |
---|
| 252 | + |
---|
| 253 | +/* Assume caller has confirmed this skb is PRP suffixed */ |
---|
| 254 | +static inline u16 prp_get_skb_sequence_nr(struct prp_rct *rct) |
---|
| 255 | +{ |
---|
| 256 | + return ntohs(rct->sequence_nr); |
---|
| 257 | +} |
---|
| 258 | + |
---|
| 259 | +static inline u16 get_prp_lan_id(struct prp_rct *rct) |
---|
| 260 | +{ |
---|
| 261 | + return ntohs(rct->lan_id_and_LSDU_size) >> 12; |
---|
| 262 | +} |
---|
| 263 | + |
---|
| 264 | +/* assume there is a valid rct */ |
---|
| 265 | +static inline bool prp_check_lsdu_size(struct sk_buff *skb, |
---|
| 266 | + struct prp_rct *rct, |
---|
| 267 | + bool is_sup) |
---|
| 268 | +{ |
---|
| 269 | + struct ethhdr *ethhdr; |
---|
| 270 | + int expected_lsdu_size; |
---|
| 271 | + |
---|
| 272 | + if (is_sup) { |
---|
| 273 | + expected_lsdu_size = HSR_V1_SUP_LSDUSIZE; |
---|
| 274 | + } else { |
---|
| 275 | + ethhdr = (struct ethhdr *)skb_mac_header(skb); |
---|
| 276 | + expected_lsdu_size = skb->len - 14; |
---|
| 277 | + if (ethhdr->h_proto == htons(ETH_P_8021Q)) |
---|
| 278 | + expected_lsdu_size -= 4; |
---|
| 279 | + } |
---|
| 280 | + |
---|
| 281 | + return (expected_lsdu_size == get_prp_LSDU_size(rct)); |
---|
| 282 | +} |
---|
| 283 | + |
---|
| 284 | +#if IS_ENABLED(CONFIG_DEBUG_FS) |
---|
| 285 | +void hsr_debugfs_rename(struct net_device *dev); |
---|
| 286 | +void hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev); |
---|
| 287 | +void hsr_debugfs_term(struct hsr_priv *priv); |
---|
| 288 | +void hsr_debugfs_create_root(void); |
---|
| 289 | +void hsr_debugfs_remove_root(void); |
---|
| 290 | +#else |
---|
| 291 | +static inline void hsr_debugfs_rename(struct net_device *dev) |
---|
| 292 | +{ |
---|
| 293 | +} |
---|
| 294 | +static inline void hsr_debugfs_init(struct hsr_priv *priv, |
---|
| 295 | + struct net_device *hsr_dev) |
---|
| 296 | +{} |
---|
| 297 | +static inline void hsr_debugfs_term(struct hsr_priv *priv) |
---|
| 298 | +{} |
---|
| 299 | +static inline void hsr_debugfs_create_root(void) |
---|
| 300 | +{} |
---|
| 301 | +static inline void hsr_debugfs_remove_root(void) |
---|
| 302 | +{} |
---|
| 303 | +#endif |
---|
| 304 | + |
---|
194 | 305 | #endif /* __HSR_PRIVATE_H */ |
---|