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

net: dsa: add trace points for FDB/MDB operations

DSA performs non-trivial housekeeping of unicast and multicast addresses
on shared (CPU and DSA) ports, and puts a bit of pressure on higher
layers, requiring them to behave correctly (remove these addresses
exactly as many times as they were added). Otherwise, either addresses
linger around forever, or DSA returns -ENOENT complaining that entries
that were already deleted must be deleted again.

To aid debugging, introduce some trace points specifically for FDB and
MDB - that's where some of the bugs still are right now.

Some bugs I have seen were also due to race conditions, see:
- 630fd4822af2 ("net: dsa: flush switchdev workqueue on bridge join error path")
- a2614140dc0f ("net: dsa: mv88e6xxx: flush switchdev FDB workqueue before removing VLAN")

so it would be good to not disturb the timing too much, hence the choice
to use trace points vs regular dev_dbg().

I've had these for some time on my computer in a less polished form, and
they've proven useful. What I found most useful was to enable
CONFIG_BOOTTIME_TRACING, add "trace_event=dsa" to the kernel cmdline,
and run "cat /sys/kernel/debug/tracing/trace". This is to debug more
complex environments with network managers started by the init system,
things like that.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Vladimir Oltean and committed by
David S. Miller
9538ebce 18bb56ab

+423 -12
+5 -1
net/dsa/Makefile
··· 16 16 slave.o \ 17 17 switch.o \ 18 18 tag.o \ 19 - tag_8021q.o 19 + tag_8021q.o \ 20 + trace.o 20 21 21 22 # tagging formats 22 23 obj-$(CONFIG_NET_DSA_TAG_AR9331) += tag_ar9331.o ··· 38 37 obj-$(CONFIG_NET_DSA_TAG_SJA1105) += tag_sja1105.o 39 38 obj-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o 40 39 obj-$(CONFIG_NET_DSA_TAG_XRS700X) += tag_xrs700x.o 40 + 41 + # for tracing framework to find trace.h 42 + CFLAGS_trace.o := -I$(src)
+50 -11
net/dsa/switch.c
··· 18 18 #include "slave.h" 19 19 #include "switch.h" 20 20 #include "tag_8021q.h" 21 + #include "trace.h" 21 22 22 23 static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds, 23 24 unsigned int ageing_time) ··· 165 164 int err = 0; 166 165 167 166 /* No need to bother with refcounting for user ports */ 168 - if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) 169 - return ds->ops->port_mdb_add(ds, port, mdb, db); 167 + if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) { 168 + err = ds->ops->port_mdb_add(ds, port, mdb, db); 169 + trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err); 170 + 171 + return err; 172 + } 170 173 171 174 mutex_lock(&dp->addr_lists_lock); 172 175 173 176 a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db); 174 177 if (a) { 175 178 refcount_inc(&a->refcount); 179 + trace_dsa_mdb_add_bump(dp, mdb->addr, mdb->vid, &db, 180 + &a->refcount); 176 181 goto out; 177 182 } 178 183 ··· 189 182 } 190 183 191 184 err = ds->ops->port_mdb_add(ds, port, mdb, db); 185 + trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err); 192 186 if (err) { 193 187 kfree(a); 194 188 goto out; ··· 217 209 int err = 0; 218 210 219 211 /* No need to bother with refcounting for user ports */ 220 - if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) 221 - return ds->ops->port_mdb_del(ds, port, mdb, db); 212 + if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) { 213 + err = ds->ops->port_mdb_del(ds, port, mdb, db); 214 + trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err); 215 + 216 + return err; 217 + } 222 218 223 219 mutex_lock(&dp->addr_lists_lock); 224 220 225 221 a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db); 226 222 if (!a) { 223 + trace_dsa_mdb_del_not_found(dp, mdb->addr, mdb->vid, &db); 227 224 err = -ENOENT; 228 225 goto out; 229 226 } 230 227 231 - if (!refcount_dec_and_test(&a->refcount)) 228 + if (!refcount_dec_and_test(&a->refcount)) { 229 + trace_dsa_mdb_del_drop(dp, mdb->addr, mdb->vid, &db, 230 + &a->refcount); 232 231 goto out; 232 + } 233 233 234 234 err = ds->ops->port_mdb_del(ds, port, mdb, db); 235 + trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err); 235 236 if (err) { 236 237 refcount_set(&a->refcount, 1); 237 238 goto out; ··· 264 247 int err = 0; 265 248 266 249 /* No need to bother with refcounting for user ports */ 267 - if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) 268 - return ds->ops->port_fdb_add(ds, port, addr, vid, db); 250 + if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) { 251 + err = ds->ops->port_fdb_add(ds, port, addr, vid, db); 252 + trace_dsa_fdb_add_hw(dp, addr, vid, &db, err); 253 + 254 + return err; 255 + } 269 256 270 257 mutex_lock(&dp->addr_lists_lock); 271 258 272 259 a = dsa_mac_addr_find(&dp->fdbs, addr, vid, db); 273 260 if (a) { 274 261 refcount_inc(&a->refcount); 262 + trace_dsa_fdb_add_bump(dp, addr, vid, &db, &a->refcount); 275 263 goto out; 276 264 } 277 265 ··· 287 265 } 288 266 289 267 err = ds->ops->port_fdb_add(ds, port, addr, vid, db); 268 + trace_dsa_fdb_add_hw(dp, addr, vid, &db, err); 290 269 if (err) { 291 270 kfree(a); 292 271 goto out; ··· 314 291 int err = 0; 315 292 316 293 /* No need to bother with refcounting for user ports */ 317 - if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) 318 - return ds->ops->port_fdb_del(ds, port, addr, vid, db); 294 + if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) { 295 + err = ds->ops->port_fdb_del(ds, port, addr, vid, db); 296 + trace_dsa_fdb_del_hw(dp, addr, vid, &db, err); 297 + 298 + return err; 299 + } 319 300 320 301 mutex_lock(&dp->addr_lists_lock); 321 302 322 303 a = dsa_mac_addr_find(&dp->fdbs, addr, vid, db); 323 304 if (!a) { 305 + trace_dsa_fdb_del_not_found(dp, addr, vid, &db); 324 306 err = -ENOENT; 325 307 goto out; 326 308 } 327 309 328 - if (!refcount_dec_and_test(&a->refcount)) 310 + if (!refcount_dec_and_test(&a->refcount)) { 311 + trace_dsa_fdb_del_drop(dp, addr, vid, &db, &a->refcount); 329 312 goto out; 313 + } 330 314 331 315 err = ds->ops->port_fdb_del(ds, port, addr, vid, db); 316 + trace_dsa_fdb_del_hw(dp, addr, vid, &db, err); 332 317 if (err) { 333 318 refcount_set(&a->refcount, 1); 334 319 goto out; ··· 363 332 a = dsa_mac_addr_find(&lag->fdbs, addr, vid, db); 364 333 if (a) { 365 334 refcount_inc(&a->refcount); 335 + trace_dsa_lag_fdb_add_bump(lag->dev, addr, vid, &db, 336 + &a->refcount); 366 337 goto out; 367 338 } 368 339 ··· 375 342 } 376 343 377 344 err = ds->ops->lag_fdb_add(ds, *lag, addr, vid, db); 345 + trace_dsa_lag_fdb_add_hw(lag->dev, addr, vid, &db, err); 378 346 if (err) { 379 347 kfree(a); 380 348 goto out; ··· 404 370 405 371 a = dsa_mac_addr_find(&lag->fdbs, addr, vid, db); 406 372 if (!a) { 373 + trace_dsa_lag_fdb_del_not_found(lag->dev, addr, vid, &db); 407 374 err = -ENOENT; 408 375 goto out; 409 376 } 410 377 411 - if (!refcount_dec_and_test(&a->refcount)) 378 + if (!refcount_dec_and_test(&a->refcount)) { 379 + trace_dsa_lag_fdb_del_drop(lag->dev, addr, vid, &db, 380 + &a->refcount); 412 381 goto out; 382 + } 413 383 414 384 err = ds->ops->lag_fdb_del(ds, *lag, addr, vid, db); 385 + trace_dsa_lag_fdb_del_hw(lag->dev, addr, vid, &db, err); 415 386 if (err) { 416 387 refcount_set(&a->refcount, 1); 417 388 goto out;
+39
net/dsa/trace.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* Copyright 2022-2023 NXP 3 + */ 4 + 5 + #define CREATE_TRACE_POINTS 6 + #include "trace.h" 7 + 8 + void dsa_db_print(const struct dsa_db *db, char buf[DSA_DB_BUFSIZ]) 9 + { 10 + switch (db->type) { 11 + case DSA_DB_PORT: 12 + sprintf(buf, "port %s", db->dp->name); 13 + break; 14 + case DSA_DB_LAG: 15 + sprintf(buf, "lag %s id %d", db->lag.dev->name, db->lag.id); 16 + break; 17 + case DSA_DB_BRIDGE: 18 + sprintf(buf, "bridge %s num %d", db->bridge.dev->name, 19 + db->bridge.num); 20 + break; 21 + default: 22 + sprintf(buf, "unknown"); 23 + break; 24 + } 25 + } 26 + 27 + const char *dsa_port_kind(const struct dsa_port *dp) 28 + { 29 + switch (dp->type) { 30 + case DSA_PORT_TYPE_USER: 31 + return "user"; 32 + case DSA_PORT_TYPE_CPU: 33 + return "cpu"; 34 + case DSA_PORT_TYPE_DSA: 35 + return "dsa"; 36 + default: 37 + return "unused"; 38 + } 39 + }
+329
net/dsa/trace.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 2 + * Copyright 2022-2023 NXP 3 + */ 4 + 5 + #undef TRACE_SYSTEM 6 + #define TRACE_SYSTEM dsa 7 + 8 + #if !defined(_NET_DSA_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) 9 + #define _NET_DSA_TRACE_H 10 + 11 + #include <net/dsa.h> 12 + #include <linux/etherdevice.h> 13 + #include <linux/refcount.h> 14 + #include <linux/tracepoint.h> 15 + 16 + /* Enough to fit "bridge %s num %d" where num has 3 digits */ 17 + #define DSA_DB_BUFSIZ (IFNAMSIZ + 16) 18 + 19 + void dsa_db_print(const struct dsa_db *db, char buf[DSA_DB_BUFSIZ]); 20 + const char *dsa_port_kind(const struct dsa_port *dp); 21 + 22 + DECLARE_EVENT_CLASS(dsa_port_addr_op_hw, 23 + 24 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, u16 vid, 25 + const struct dsa_db *db, int err), 26 + 27 + TP_ARGS(dp, addr, vid, db, err), 28 + 29 + TP_STRUCT__entry( 30 + __string(dev, dev_name(dp->ds->dev)) 31 + __string(kind, dsa_port_kind(dp)) 32 + __field(int, port) 33 + __array(unsigned char, addr, ETH_ALEN) 34 + __field(u16, vid) 35 + __array(char, db_buf, DSA_DB_BUFSIZ) 36 + __field(int, err) 37 + ), 38 + 39 + TP_fast_assign( 40 + __assign_str(dev, dev_name(dp->ds->dev)); 41 + __assign_str(kind, dsa_port_kind(dp)); 42 + __entry->port = dp->index; 43 + ether_addr_copy(__entry->addr, addr); 44 + __entry->vid = vid; 45 + dsa_db_print(db, __entry->db_buf); 46 + __entry->err = err; 47 + ), 48 + 49 + TP_printk("%s %s port %d addr %pM vid %u db \"%s\" err %d", 50 + __get_str(dev), __get_str(kind), __entry->port, __entry->addr, 51 + __entry->vid, __entry->db_buf, __entry->err) 52 + ); 53 + 54 + /* Add unicast/multicast address to hardware, either on user ports 55 + * (where no refcounting is kept), or on shared ports when the entry 56 + * is first seen and its refcount is 1. 57 + */ 58 + DEFINE_EVENT(dsa_port_addr_op_hw, dsa_fdb_add_hw, 59 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 60 + u16 vid, const struct dsa_db *db, int err), 61 + TP_ARGS(dp, addr, vid, db, err)); 62 + 63 + DEFINE_EVENT(dsa_port_addr_op_hw, dsa_mdb_add_hw, 64 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 65 + u16 vid, const struct dsa_db *db, int err), 66 + TP_ARGS(dp, addr, vid, db, err)); 67 + 68 + /* Delete unicast/multicast address from hardware, either on user ports or 69 + * when the refcount on shared ports reaches 0 70 + */ 71 + DEFINE_EVENT(dsa_port_addr_op_hw, dsa_fdb_del_hw, 72 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 73 + u16 vid, const struct dsa_db *db, int err), 74 + TP_ARGS(dp, addr, vid, db, err)); 75 + 76 + DEFINE_EVENT(dsa_port_addr_op_hw, dsa_mdb_del_hw, 77 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 78 + u16 vid, const struct dsa_db *db, int err), 79 + TP_ARGS(dp, addr, vid, db, err)); 80 + 81 + DECLARE_EVENT_CLASS(dsa_port_addr_op_refcount, 82 + 83 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, u16 vid, 84 + const struct dsa_db *db, const refcount_t *refcount), 85 + 86 + TP_ARGS(dp, addr, vid, db, refcount), 87 + 88 + TP_STRUCT__entry( 89 + __string(dev, dev_name(dp->ds->dev)) 90 + __string(kind, dsa_port_kind(dp)) 91 + __field(int, port) 92 + __array(unsigned char, addr, ETH_ALEN) 93 + __field(u16, vid) 94 + __array(char, db_buf, DSA_DB_BUFSIZ) 95 + __field(unsigned int, refcount) 96 + ), 97 + 98 + TP_fast_assign( 99 + __assign_str(dev, dev_name(dp->ds->dev)); 100 + __assign_str(kind, dsa_port_kind(dp)); 101 + __entry->port = dp->index; 102 + ether_addr_copy(__entry->addr, addr); 103 + __entry->vid = vid; 104 + dsa_db_print(db, __entry->db_buf); 105 + __entry->refcount = refcount_read(refcount); 106 + ), 107 + 108 + TP_printk("%s %s port %d addr %pM vid %u db \"%s\" refcount %u", 109 + __get_str(dev), __get_str(kind), __entry->port, __entry->addr, 110 + __entry->vid, __entry->db_buf, __entry->refcount) 111 + ); 112 + 113 + /* Bump the refcount of an existing unicast/multicast address on shared ports */ 114 + DEFINE_EVENT(dsa_port_addr_op_refcount, dsa_fdb_add_bump, 115 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 116 + u16 vid, const struct dsa_db *db, 117 + const refcount_t *refcount), 118 + TP_ARGS(dp, addr, vid, db, refcount)); 119 + 120 + DEFINE_EVENT(dsa_port_addr_op_refcount, dsa_mdb_add_bump, 121 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 122 + u16 vid, const struct dsa_db *db, 123 + const refcount_t *refcount), 124 + TP_ARGS(dp, addr, vid, db, refcount)); 125 + 126 + /* Drop the refcount of a multicast address that we still keep on 127 + * shared ports 128 + */ 129 + DEFINE_EVENT(dsa_port_addr_op_refcount, dsa_fdb_del_drop, 130 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 131 + u16 vid, const struct dsa_db *db, 132 + const refcount_t *refcount), 133 + TP_ARGS(dp, addr, vid, db, refcount)); 134 + 135 + DEFINE_EVENT(dsa_port_addr_op_refcount, dsa_mdb_del_drop, 136 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 137 + u16 vid, const struct dsa_db *db, 138 + const refcount_t *refcount), 139 + TP_ARGS(dp, addr, vid, db, refcount)); 140 + 141 + DECLARE_EVENT_CLASS(dsa_port_addr_del_not_found, 142 + 143 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, u16 vid, 144 + const struct dsa_db *db), 145 + 146 + TP_ARGS(dp, addr, vid, db), 147 + 148 + TP_STRUCT__entry( 149 + __string(dev, dev_name(dp->ds->dev)) 150 + __string(kind, dsa_port_kind(dp)) 151 + __field(int, port) 152 + __array(unsigned char, addr, ETH_ALEN) 153 + __field(u16, vid) 154 + __array(char, db_buf, DSA_DB_BUFSIZ) 155 + ), 156 + 157 + TP_fast_assign( 158 + __assign_str(dev, dev_name(dp->ds->dev)); 159 + __assign_str(kind, dsa_port_kind(dp)); 160 + __entry->port = dp->index; 161 + ether_addr_copy(__entry->addr, addr); 162 + __entry->vid = vid; 163 + dsa_db_print(db, __entry->db_buf); 164 + ), 165 + 166 + TP_printk("%s %s port %d addr %pM vid %u db \"%s\"", 167 + __get_str(dev), __get_str(kind), __entry->port, 168 + __entry->addr, __entry->vid, __entry->db_buf) 169 + ); 170 + 171 + /* Attempt to delete a unicast/multicast address on shared ports for which 172 + * the delete operation was called more times than the addition 173 + */ 174 + DEFINE_EVENT(dsa_port_addr_del_not_found, dsa_fdb_del_not_found, 175 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 176 + u16 vid, const struct dsa_db *db), 177 + TP_ARGS(dp, addr, vid, db)); 178 + 179 + DEFINE_EVENT(dsa_port_addr_del_not_found, dsa_mdb_del_not_found, 180 + TP_PROTO(const struct dsa_port *dp, const unsigned char *addr, 181 + u16 vid, const struct dsa_db *db), 182 + TP_ARGS(dp, addr, vid, db)); 183 + 184 + TRACE_EVENT(dsa_lag_fdb_add_hw, 185 + 186 + TP_PROTO(const struct net_device *lag_dev, const unsigned char *addr, 187 + u16 vid, const struct dsa_db *db, int err), 188 + 189 + TP_ARGS(lag_dev, addr, vid, db, err), 190 + 191 + TP_STRUCT__entry( 192 + __string(dev, lag_dev->name) 193 + __array(unsigned char, addr, ETH_ALEN) 194 + __field(u16, vid) 195 + __array(char, db_buf, DSA_DB_BUFSIZ) 196 + __field(int, err) 197 + ), 198 + 199 + TP_fast_assign( 200 + __assign_str(dev, lag_dev->name); 201 + ether_addr_copy(__entry->addr, addr); 202 + __entry->vid = vid; 203 + dsa_db_print(db, __entry->db_buf); 204 + __entry->err = err; 205 + ), 206 + 207 + TP_printk("%s addr %pM vid %u db \"%s\" err %d", 208 + __get_str(dev), __entry->addr, __entry->vid, 209 + __entry->db_buf, __entry->err) 210 + ); 211 + 212 + TRACE_EVENT(dsa_lag_fdb_add_bump, 213 + 214 + TP_PROTO(const struct net_device *lag_dev, const unsigned char *addr, 215 + u16 vid, const struct dsa_db *db, const refcount_t *refcount), 216 + 217 + TP_ARGS(lag_dev, addr, vid, db, refcount), 218 + 219 + TP_STRUCT__entry( 220 + __string(dev, lag_dev->name) 221 + __array(unsigned char, addr, ETH_ALEN) 222 + __field(u16, vid) 223 + __array(char, db_buf, DSA_DB_BUFSIZ) 224 + __field(unsigned int, refcount) 225 + ), 226 + 227 + TP_fast_assign( 228 + __assign_str(dev, lag_dev->name); 229 + ether_addr_copy(__entry->addr, addr); 230 + __entry->vid = vid; 231 + dsa_db_print(db, __entry->db_buf); 232 + __entry->refcount = refcount_read(refcount); 233 + ), 234 + 235 + TP_printk("%s addr %pM vid %u db \"%s\" refcount %u", 236 + __get_str(dev), __entry->addr, __entry->vid, 237 + __entry->db_buf, __entry->refcount) 238 + ); 239 + 240 + TRACE_EVENT(dsa_lag_fdb_del_hw, 241 + 242 + TP_PROTO(const struct net_device *lag_dev, const unsigned char *addr, 243 + u16 vid, const struct dsa_db *db, int err), 244 + 245 + TP_ARGS(lag_dev, addr, vid, db, err), 246 + 247 + TP_STRUCT__entry( 248 + __string(dev, lag_dev->name) 249 + __array(unsigned char, addr, ETH_ALEN) 250 + __field(u16, vid) 251 + __array(char, db_buf, DSA_DB_BUFSIZ) 252 + __field(int, err) 253 + ), 254 + 255 + TP_fast_assign( 256 + __assign_str(dev, lag_dev->name); 257 + ether_addr_copy(__entry->addr, addr); 258 + __entry->vid = vid; 259 + dsa_db_print(db, __entry->db_buf); 260 + __entry->err = err; 261 + ), 262 + 263 + TP_printk("%s addr %pM vid %u db \"%s\" err %d", 264 + __get_str(dev), __entry->addr, __entry->vid, 265 + __entry->db_buf, __entry->err) 266 + ); 267 + 268 + TRACE_EVENT(dsa_lag_fdb_del_drop, 269 + 270 + TP_PROTO(const struct net_device *lag_dev, const unsigned char *addr, 271 + u16 vid, const struct dsa_db *db, const refcount_t *refcount), 272 + 273 + TP_ARGS(lag_dev, addr, vid, db, refcount), 274 + 275 + TP_STRUCT__entry( 276 + __string(dev, lag_dev->name) 277 + __array(unsigned char, addr, ETH_ALEN) 278 + __field(u16, vid) 279 + __array(char, db_buf, DSA_DB_BUFSIZ) 280 + __field(unsigned int, refcount) 281 + ), 282 + 283 + TP_fast_assign( 284 + __assign_str(dev, lag_dev->name); 285 + ether_addr_copy(__entry->addr, addr); 286 + __entry->vid = vid; 287 + dsa_db_print(db, __entry->db_buf); 288 + __entry->refcount = refcount_read(refcount); 289 + ), 290 + 291 + TP_printk("%s addr %pM vid %u db \"%s\" refcount %u", 292 + __get_str(dev), __entry->addr, __entry->vid, 293 + __entry->db_buf, __entry->refcount) 294 + ); 295 + 296 + TRACE_EVENT(dsa_lag_fdb_del_not_found, 297 + 298 + TP_PROTO(const struct net_device *lag_dev, const unsigned char *addr, 299 + u16 vid, const struct dsa_db *db), 300 + 301 + TP_ARGS(lag_dev, addr, vid, db), 302 + 303 + TP_STRUCT__entry( 304 + __string(dev, lag_dev->name) 305 + __array(unsigned char, addr, ETH_ALEN) 306 + __field(u16, vid) 307 + __array(char, db_buf, DSA_DB_BUFSIZ) 308 + ), 309 + 310 + TP_fast_assign( 311 + __assign_str(dev, lag_dev->name); 312 + ether_addr_copy(__entry->addr, addr); 313 + __entry->vid = vid; 314 + dsa_db_print(db, __entry->db_buf); 315 + ), 316 + 317 + TP_printk("%s addr %pM vid %u db \"%s\"", 318 + __get_str(dev), __entry->addr, __entry->vid, __entry->db_buf) 319 + ); 320 + 321 + #endif /* _NET_DSA_TRACE_H */ 322 + 323 + /* We don't want to use include/trace/events */ 324 + #undef TRACE_INCLUDE_PATH 325 + #define TRACE_INCLUDE_PATH . 326 + #undef TRACE_INCLUDE_FILE 327 + #define TRACE_INCLUDE_FILE trace 328 + /* This part must be outside protection */ 329 + #include <trace/define_trace.h>