at master 13 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 2 * Copyright 2019-2021 NXP 3 */ 4 5#ifndef _NET_DSA_TAG_OCELOT_H 6#define _NET_DSA_TAG_OCELOT_H 7 8#include <linux/if_bridge.h> 9#include <linux/if_vlan.h> 10#include <linux/kthread.h> 11#include <linux/packing.h> 12#include <linux/skbuff.h> 13#include <net/dsa.h> 14 15struct ocelot_skb_cb { 16 struct sk_buff *clone; 17 unsigned int ptp_class; /* valid only for clones */ 18 unsigned long ptp_tx_time; /* valid only for clones */ 19 u32 tstamp_lo; 20 u8 ptp_cmd; 21 u8 ts_id; 22}; 23 24#define OCELOT_SKB_CB(skb) \ 25 ((struct ocelot_skb_cb *)((skb)->cb)) 26 27#define IFH_TAG_TYPE_C 0 28#define IFH_TAG_TYPE_S 1 29 30#define IFH_REW_OP_NOOP 0x0 31#define IFH_REW_OP_DSCP 0x1 32#define IFH_REW_OP_ONE_STEP_PTP 0x2 33#define IFH_REW_OP_TWO_STEP_PTP 0x3 34#define IFH_REW_OP_ORIGIN_PTP 0x5 35 36#define OCELOT_TAG_LEN 16 37#define OCELOT_SHORT_PREFIX_LEN 4 38#define OCELOT_LONG_PREFIX_LEN 16 39#define OCELOT_TOTAL_TAG_LEN (OCELOT_SHORT_PREFIX_LEN + OCELOT_TAG_LEN) 40 41/* The CPU injection header and the CPU extraction header can have 3 types of 42 * prefixes: long, short and no prefix. The format of the header itself is the 43 * same in all 3 cases. 44 * 45 * Extraction with long prefix: 46 * 47 * +-------------------+-------------------+------+------+------------+-------+ 48 * | ff:ff:ff:ff:ff:ff | fe:ff:ff:ff:ff:ff | 8880 | 000a | extraction | frame | 49 * | | | | | header | | 50 * +-------------------+-------------------+------+------+------------+-------+ 51 * 48 bits 48 bits 16 bits 16 bits 128 bits 52 * 53 * Extraction with short prefix: 54 * 55 * +------+------+------------+-------+ 56 * | 8880 | 000a | extraction | frame | 57 * | | | header | | 58 * +------+------+------------+-------+ 59 * 16 bits 16 bits 128 bits 60 * 61 * Extraction with no prefix: 62 * 63 * +------------+-------+ 64 * | extraction | frame | 65 * | header | | 66 * +------------+-------+ 67 * 128 bits 68 * 69 * 70 * Injection with long prefix: 71 * 72 * +-------------------+-------------------+------+------+------------+-------+ 73 * | any dmac | any smac | 8880 | 000a | injection | frame | 74 * | | | | | header | | 75 * +-------------------+-------------------+------+------+------------+-------+ 76 * 48 bits 48 bits 16 bits 16 bits 128 bits 77 * 78 * Injection with short prefix: 79 * 80 * +------+------+------------+-------+ 81 * | 8880 | 000a | injection | frame | 82 * | | | header | | 83 * +------+------+------------+-------+ 84 * 16 bits 16 bits 128 bits 85 * 86 * Injection with no prefix: 87 * 88 * +------------+-------+ 89 * | injection | frame | 90 * | header | | 91 * +------------+-------+ 92 * 128 bits 93 * 94 * The injection header looks like this (network byte order, bit 127 95 * is part of lowest address byte in memory, bit 0 is part of highest 96 * address byte): 97 * 98 * +------+------+------+------+------+------+------+------+ 99 * 127:120 |BYPASS| MASQ | MASQ_PORT |REW_OP|REW_OP| 100 * +------+------+------+------+------+------+------+------+ 101 * 119:112 | REW_OP | 102 * +------+------+------+------+------+------+------+------+ 103 * 111:104 | REW_VAL | 104 * +------+------+------+------+------+------+------+------+ 105 * 103: 96 | REW_VAL | 106 * +------+------+------+------+------+------+------+------+ 107 * 95: 88 | REW_VAL | 108 * +------+------+------+------+------+------+------+------+ 109 * 87: 80 | REW_VAL | 110 * +------+------+------+------+------+------+------+------+ 111 * 79: 72 | RSV | 112 * +------+------+------+------+------+------+------+------+ 113 * 71: 64 | RSV | DEST | 114 * +------+------+------+------+------+------+------+------+ 115 * 63: 56 | DEST | 116 * +------+------+------+------+------+------+------+------+ 117 * 55: 48 | RSV | 118 * +------+------+------+------+------+------+------+------+ 119 * 47: 40 | RSV | SRC_PORT | RSV |TFRM_TIMER| 120 * +------+------+------+------+------+------+------+------+ 121 * 39: 32 | TFRM_TIMER | RSV | 122 * +------+------+------+------+------+------+------+------+ 123 * 31: 24 | RSV | DP | POP_CNT | CPUQ | 124 * +------+------+------+------+------+------+------+------+ 125 * 23: 16 | CPUQ | QOS_CLASS |TAG_TYPE| 126 * +------+------+------+------+------+------+------+------+ 127 * 15: 8 | PCP | DEI | VID | 128 * +------+------+------+------+------+------+------+------+ 129 * 7: 0 | VID | 130 * +------+------+------+------+------+------+------+------+ 131 * 132 * And the extraction header looks like this: 133 * 134 * +------+------+------+------+------+------+------+------+ 135 * 127:120 | RSV | REW_OP | 136 * +------+------+------+------+------+------+------+------+ 137 * 119:112 | REW_OP | REW_VAL | 138 * +------+------+------+------+------+------+------+------+ 139 * 111:104 | REW_VAL | 140 * +------+------+------+------+------+------+------+------+ 141 * 103: 96 | REW_VAL | 142 * +------+------+------+------+------+------+------+------+ 143 * 95: 88 | REW_VAL | 144 * +------+------+------+------+------+------+------+------+ 145 * 87: 80 | REW_VAL | LLEN | 146 * +------+------+------+------+------+------+------+------+ 147 * 79: 72 | LLEN | WLEN | 148 * +------+------+------+------+------+------+------+------+ 149 * 71: 64 | WLEN | RSV | 150 * +------+------+------+------+------+------+------+------+ 151 * 63: 56 | RSV | 152 * +------+------+------+------+------+------+------+------+ 153 * 55: 48 | RSV | 154 * +------+------+------+------+------+------+------+------+ 155 * 47: 40 | RSV | SRC_PORT | ACL_ID | 156 * +------+------+------+------+------+------+------+------+ 157 * 39: 32 | ACL_ID | RSV | SFLOW_ID | 158 * +------+------+------+------+------+------+------+------+ 159 * 31: 24 |ACL_HIT| DP | LRN_FLAGS | CPUQ | 160 * +------+------+------+------+------+------+------+------+ 161 * 23: 16 | CPUQ | QOS_CLASS |TAG_TYPE| 162 * +------+------+------+------+------+------+------+------+ 163 * 15: 8 | PCP | DEI | VID | 164 * +------+------+------+------+------+------+------+------+ 165 * 7: 0 | VID | 166 * +------+------+------+------+------+------+------+------+ 167 */ 168 169struct felix_deferred_xmit_work { 170 struct dsa_port *dp; 171 struct sk_buff *skb; 172 struct kthread_work work; 173}; 174 175struct ocelot_8021q_tagger_data { 176 void (*xmit_work_fn)(struct kthread_work *work); 177}; 178 179static inline struct ocelot_8021q_tagger_data * 180ocelot_8021q_tagger_data(struct dsa_switch *ds) 181{ 182 BUG_ON(ds->dst->tag_ops->proto != DSA_TAG_PROTO_OCELOT_8021Q); 183 184 return ds->tagger_data; 185} 186 187static inline void ocelot_xfh_get_rew_val(void *extraction, u64 *rew_val) 188{ 189 packing(extraction, rew_val, 116, 85, OCELOT_TAG_LEN, UNPACK, 0); 190} 191 192static inline void ocelot_xfh_get_len(void *extraction, u64 *len) 193{ 194 u64 llen, wlen; 195 196 packing(extraction, &llen, 84, 79, OCELOT_TAG_LEN, UNPACK, 0); 197 packing(extraction, &wlen, 78, 71, OCELOT_TAG_LEN, UNPACK, 0); 198 199 *len = 60 * wlen + llen - 80; 200} 201 202static inline void ocelot_xfh_get_src_port(void *extraction, u64 *src_port) 203{ 204 packing(extraction, src_port, 46, 43, OCELOT_TAG_LEN, UNPACK, 0); 205} 206 207static inline void ocelot_xfh_get_qos_class(void *extraction, u64 *qos_class) 208{ 209 packing(extraction, qos_class, 19, 17, OCELOT_TAG_LEN, UNPACK, 0); 210} 211 212static inline void ocelot_xfh_get_tag_type(void *extraction, u64 *tag_type) 213{ 214 packing(extraction, tag_type, 16, 16, OCELOT_TAG_LEN, UNPACK, 0); 215} 216 217static inline void ocelot_xfh_get_vlan_tci(void *extraction, u64 *vlan_tci) 218{ 219 packing(extraction, vlan_tci, 15, 0, OCELOT_TAG_LEN, UNPACK, 0); 220} 221 222static inline void ocelot_ifh_set_bypass(void *injection, u64 bypass) 223{ 224 packing(injection, &bypass, 127, 127, OCELOT_TAG_LEN, PACK, 0); 225} 226 227static inline void ocelot_ifh_set_rew_op(void *injection, u64 rew_op) 228{ 229 packing(injection, &rew_op, 125, 117, OCELOT_TAG_LEN, PACK, 0); 230} 231 232static inline void ocelot_ifh_set_dest(void *injection, u64 dest) 233{ 234 packing(injection, &dest, 67, 56, OCELOT_TAG_LEN, PACK, 0); 235} 236 237static inline void ocelot_ifh_set_qos_class(void *injection, u64 qos_class) 238{ 239 packing(injection, &qos_class, 19, 17, OCELOT_TAG_LEN, PACK, 0); 240} 241 242static inline void seville_ifh_set_dest(void *injection, u64 dest) 243{ 244 packing(injection, &dest, 67, 57, OCELOT_TAG_LEN, PACK, 0); 245} 246 247static inline void ocelot_ifh_set_src(void *injection, u64 src) 248{ 249 packing(injection, &src, 46, 43, OCELOT_TAG_LEN, PACK, 0); 250} 251 252static inline void ocelot_ifh_set_tag_type(void *injection, u64 tag_type) 253{ 254 packing(injection, &tag_type, 16, 16, OCELOT_TAG_LEN, PACK, 0); 255} 256 257static inline void ocelot_ifh_set_vlan_tci(void *injection, u64 vlan_tci) 258{ 259 packing(injection, &vlan_tci, 15, 0, OCELOT_TAG_LEN, PACK, 0); 260} 261 262/* Determine the PTP REW_OP to use for injecting the given skb */ 263static inline u32 ocelot_ptp_rew_op(struct sk_buff *skb) 264{ 265 struct sk_buff *clone = OCELOT_SKB_CB(skb)->clone; 266 u8 ptp_cmd = OCELOT_SKB_CB(skb)->ptp_cmd; 267 u32 rew_op = 0; 268 269 if (ptp_cmd == IFH_REW_OP_TWO_STEP_PTP && clone) { 270 rew_op = ptp_cmd; 271 rew_op |= OCELOT_SKB_CB(clone)->ts_id << 3; 272 } else if (ptp_cmd == IFH_REW_OP_ORIGIN_PTP) { 273 rew_op = ptp_cmd; 274 } 275 276 return rew_op; 277} 278 279/** 280 * ocelot_xmit_get_vlan_info: Determine VLAN_TCI and TAG_TYPE for injected frame 281 * @skb: Pointer to socket buffer 282 * @br: Pointer to bridge device that the port is under, if any 283 * @vlan_tci: 284 * @tag_type: 285 * 286 * If the port is under a VLAN-aware bridge, remove the VLAN header from the 287 * payload and move it into the DSA tag, which will make the switch classify 288 * the packet to the bridge VLAN. Otherwise, leave the classified VLAN at zero, 289 * which is the pvid of standalone ports (OCELOT_STANDALONE_PVID), although not 290 * of VLAN-unaware bridge ports (that would be ocelot_vlan_unaware_pvid()). 291 * Anyway, VID 0 is fine because it is stripped on egress for these port modes, 292 * and source address learning is not performed for packets injected from the 293 * CPU anyway, so it doesn't matter that the VID is "wrong". 294 */ 295static inline void ocelot_xmit_get_vlan_info(struct sk_buff *skb, 296 struct net_device *br, 297 u64 *vlan_tci, u64 *tag_type) 298{ 299 struct vlan_ethhdr *hdr; 300 u16 proto, tci; 301 302 if (!br || !br_vlan_enabled(br)) { 303 *vlan_tci = 0; 304 *tag_type = IFH_TAG_TYPE_C; 305 return; 306 } 307 308 hdr = (struct vlan_ethhdr *)skb_mac_header(skb); 309 br_vlan_get_proto(br, &proto); 310 311 if (ntohs(hdr->h_vlan_proto) == proto) { 312 vlan_remove_tag(skb, &tci); 313 *vlan_tci = tci; 314 } else { 315 rcu_read_lock(); 316 br_vlan_get_pvid_rcu(br, &tci); 317 rcu_read_unlock(); 318 *vlan_tci = tci; 319 } 320 321 *tag_type = (proto != ETH_P_8021Q) ? IFH_TAG_TYPE_S : IFH_TAG_TYPE_C; 322} 323 324#endif