Based on kernel version 4.16.1. Page generated on 2018-04-09 11:53 EST.
1 Distributed Switch Architecture 2 =============================== 3 4 Introduction 5 ============ 6 7 This document describes the Distributed Switch Architecture (DSA) subsystem 8 design principles, limitations, interactions with other subsystems, and how to 9 develop drivers for this subsystem as well as a TODO for developers interested 10 in joining the effort. 11 12 Design principles 13 ================= 14 15 The Distributed Switch Architecture is a subsystem which was primarily designed 16 to support Marvell Ethernet switches (MV88E6xxx, a.k.a Linkstreet product line) 17 using Linux, but has since evolved to support other vendors as well. 18 19 The original philosophy behind this design was to be able to use unmodified 20 Linux tools such as bridge, iproute2, ifconfig to work transparently whether 21 they configured/queried a switch port network device or a regular network 22 device. 23 24 An Ethernet switch is typically comprised of multiple front-panel ports, and one 25 or more CPU or management port. The DSA subsystem currently relies on the 26 presence of a management port connected to an Ethernet controller capable of 27 receiving Ethernet frames from the switch. This is a very common setup for all 28 kinds of Ethernet switches found in Small Home and Office products: routers, 29 gateways, or even top-of-the rack switches. This host Ethernet controller will 30 be later referred to as "master" and "cpu" in DSA terminology and code. 31 32 The D in DSA stands for Distributed, because the subsystem has been designed 33 with the ability to configure and manage cascaded switches on top of each other 34 using upstream and downstream Ethernet links between switches. These specific 35 ports are referred to as "dsa" ports in DSA terminology and code. A collection 36 of multiple switches connected to each other is called a "switch tree". 37 38 For each front-panel port, DSA will create specialized network devices which are 39 used as controlling and data-flowing endpoints for use by the Linux networking 40 stack. These specialized network interfaces are referred to as "slave" network 41 interfaces in DSA terminology and code. 42 43 The ideal case for using DSA is when an Ethernet switch supports a "switch tag" 44 which is a hardware feature making the switch insert a specific tag for each 45 Ethernet frames it received to/from specific ports to help the management 46 interface figure out: 47 48 - what port is this frame coming from 49 - what was the reason why this frame got forwarded 50 - how to send CPU originated traffic to specific ports 51 52 The subsystem does support switches not capable of inserting/stripping tags, but 53 the features might be slightly limited in that case (traffic separation relies 54 on Port-based VLAN IDs). 55 56 Note that DSA does not currently create network interfaces for the "cpu" and 57 "dsa" ports because: 58 59 - the "cpu" port is the Ethernet switch facing side of the management 60 controller, and as such, would create a duplication of feature, since you 61 would get two interfaces for the same conduit: master netdev, and "cpu" netdev 62 63 - the "dsa" port(s) are just conduits between two or more switches, and as such 64 cannot really be used as proper network interfaces either, only the 65 downstream, or the top-most upstream interface makes sense with that model 66 67 Switch tagging protocols 68 ------------------------ 69 70 DSA currently supports 5 different tagging protocols, and a tag-less mode as 71 well. The different protocols are implemented in: 72 73 net/dsa/tag_trailer.c: Marvell's 4 trailer tag mode (legacy) 74 net/dsa/tag_dsa.c: Marvell's original DSA tag 75 net/dsa/tag_edsa.c: Marvell's enhanced DSA tag 76 net/dsa/tag_brcm.c: Broadcom's 4 bytes tag 77 net/dsa/tag_qca.c: Qualcomm's 2 bytes tag 78 79 The exact format of the tag protocol is vendor specific, but in general, they 80 all contain something which: 81 82 - identifies which port the Ethernet frame came from/should be sent to 83 - provides a reason why this frame was forwarded to the management interface 84 85 Master network devices 86 ---------------------- 87 88 Master network devices are regular, unmodified Linux network device drivers for 89 the CPU/management Ethernet interface. Such a driver might occasionally need to 90 know whether DSA is enabled (e.g.: to enable/disable specific offload features), 91 but the DSA subsystem has been proven to work with industry standard drivers: 92 e1000e, mv643xx_eth etc. without having to introduce modifications to these 93 drivers. Such network devices are also often referred to as conduit network 94 devices since they act as a pipe between the host processor and the hardware 95 Ethernet switch. 96 97 Networking stack hooks 98 ---------------------- 99 100 When a master netdev is used with DSA, a small hook is placed in in the 101 networking stack is in order to have the DSA subsystem process the Ethernet 102 switch specific tagging protocol. DSA accomplishes this by registering a 103 specific (and fake) Ethernet type (later becoming skb->protocol) with the 104 networking stack, this is also known as a ptype or packet_type. A typical 105 Ethernet Frame receive sequence looks like this: 106 107 Master network device (e.g.: e1000e): 108 109 Receive interrupt fires: 110 - receive function is invoked 111 - basic packet processing is done: getting length, status etc. 112 - packet is prepared to be processed by the Ethernet layer by calling 113 eth_type_trans 114 115 net/ethernet/eth.c: 116 117 eth_type_trans(skb, dev) 118 if (dev->dsa_ptr != NULL) 119 -> skb->protocol = ETH_P_XDSA 120 121 drivers/net/ethernet/*: 122 123 netif_receive_skb(skb) 124 -> iterate over registered packet_type 125 -> invoke handler for ETH_P_XDSA, calls dsa_switch_rcv() 126 127 net/dsa/dsa.c: 128 -> dsa_switch_rcv() 129 -> invoke switch tag specific protocol handler in 130 net/dsa/tag_*.c 131 132 net/dsa/tag_*.c: 133 -> inspect and strip switch tag protocol to determine originating port 134 -> locate per-port network device 135 -> invoke eth_type_trans() with the DSA slave network device 136 -> invoked netif_receive_skb() 137 138 Past this point, the DSA slave network devices get delivered regular Ethernet 139 frames that can be processed by the networking stack. 140 141 Slave network devices 142 --------------------- 143 144 Slave network devices created by DSA are stacked on top of their master network 145 device, each of these network interfaces will be responsible for being a 146 controlling and data-flowing end-point for each front-panel port of the switch. 147 These interfaces are specialized in order to: 148 149 - insert/remove the switch tag protocol (if it exists) when sending traffic 150 to/from specific switch ports 151 - query the switch for ethtool operations: statistics, link state, 152 Wake-on-LAN, register dumps... 153 - external/internal PHY management: link, auto-negotiation etc. 154 155 These slave network devices have custom net_device_ops and ethtool_ops function 156 pointers which allow DSA to introduce a level of layering between the networking 157 stack/ethtool, and the switch driver implementation. 158 159 Upon frame transmission from these slave network devices, DSA will look up which 160 switch tagging protocol is currently registered with these network devices, and 161 invoke a specific transmit routine which takes care of adding the relevant 162 switch tag in the Ethernet frames. 163 164 These frames are then queued for transmission using the master network device 165 ndo_start_xmit() function, since they contain the appropriate switch tag, the 166 Ethernet switch will be able to process these incoming frames from the 167 management interface and delivers these frames to the physical switch port. 168 169 Graphical representation 170 ------------------------ 171 172 Summarized, this is basically how DSA looks like from a network device 173 perspective: 174 175 176 |--------------------------- 177 | CPU network device (eth0)| 178 ---------------------------- 179 | <tag added by switch | 180 | | 181 | | 182 | tag added by CPU> | 183 |--------------------------------------------| 184 | Switch driver | 185 |--------------------------------------------| 186 || || || 187 |-------| |-------| |-------| 188 | sw0p0 | | sw0p1 | | sw0p2 | 189 |-------| |-------| |-------| 190 191 Slave MDIO bus 192 -------------- 193 194 In order to be able to read to/from a switch PHY built into it, DSA creates a 195 slave MDIO bus which allows a specific switch driver to divert and intercept 196 MDIO reads/writes towards specific PHY addresses. In most MDIO-connected 197 switches, these functions would utilize direct or indirect PHY addressing mode 198 to return standard MII registers from the switch builtin PHYs, allowing the PHY 199 library and/or to return link status, link partner pages, auto-negotiation 200 results etc.. 201 202 For Ethernet switches which have both external and internal MDIO busses, the 203 slave MII bus can be utilized to mux/demux MDIO reads and writes towards either 204 internal or external MDIO devices this switch might be connected to: internal 205 PHYs, external PHYs, or even external switches. 206 207 Data structures 208 --------------- 209 210 DSA data structures are defined in include/net/dsa.h as well as 211 net/dsa/dsa_priv.h. 212 213 dsa_chip_data: platform data configuration for a given switch device, this 214 structure describes a switch device's parent device, its address, as well as 215 various properties of its ports: names/labels, and finally a routing table 216 indication (when cascading switches) 217 218 dsa_platform_data: platform device configuration data which can reference a 219 collection of dsa_chip_data structure if multiples switches are cascaded, the 220 master network device this switch tree is attached to needs to be referenced 221 222 dsa_switch_tree: structure assigned to the master network device under 223 "dsa_ptr", this structure references a dsa_platform_data structure as well as 224 the tagging protocol supported by the switch tree, and which receive/transmit 225 function hooks should be invoked, information about the directly attached switch 226 is also provided: CPU port. Finally, a collection of dsa_switch are referenced 227 to address individual switches in the tree. 228 229 dsa_switch: structure describing a switch device in the tree, referencing a 230 dsa_switch_tree as a backpointer, slave network devices, master network device, 231 and a reference to the backing dsa_switch_ops 232 233 dsa_switch_ops: structure referencing function pointers, see below for a full 234 description. 235 236 Design limitations 237 ================== 238 239 DSA is a platform device driver 240 ------------------------------- 241 242 DSA is implemented as a DSA platform device driver which is convenient because 243 it will register the entire DSA switch tree attached to a master network device 244 in one-shot, facilitating the device creation and simplifying the device driver 245 model a bit, this comes however with a number of limitations: 246 247 - building DSA and its switch drivers as modules is currently not working 248 - the device driver parenting does not necessarily reflect the original 249 bus/device the switch can be created from 250 - supporting non-MDIO and non-MMIO (platform) switches is not possible 251 252 Limits on the number of devices and ports 253 ----------------------------------------- 254 255 DSA currently limits the number of maximum switches within a tree to 4 256 (DSA_MAX_SWITCHES), and the number of ports per switch to 12 (DSA_MAX_PORTS). 257 These limits could be extended to support larger configurations would this need 258 arise. 259 260 Lack of CPU/DSA network devices 261 ------------------------------- 262 263 DSA does not currently create slave network devices for the CPU or DSA ports, as 264 described before. This might be an issue in the following cases: 265 266 - inability to fetch switch CPU port statistics counters using ethtool, which 267 can make it harder to debug MDIO switch connected using xMII interfaces 268 269 - inability to configure the CPU port link parameters based on the Ethernet 270 controller capabilities attached to it: http://patchwork.ozlabs.org/patch/509806/ 271 272 - inability to configure specific VLAN IDs / trunking VLANs between switches 273 when using a cascaded setup 274 275 Common pitfalls using DSA setups 276 -------------------------------- 277 278 Once a master network device is configured to use DSA (dev->dsa_ptr becomes 279 non-NULL), and the switch behind it expects a tagging protocol, this network 280 interface can only exclusively be used as a conduit interface. Sending packets 281 directly through this interface (e.g.: opening a socket using this interface) 282 will not make us go through the switch tagging protocol transmit function, so 283 the Ethernet switch on the other end, expecting a tag will typically drop this 284 frame. 285 286 Slave network devices check that the master network device is UP before allowing 287 you to administratively bring UP these slave network devices. A common 288 configuration mistake is forgetting to bring UP the master network device first. 289 290 Interactions with other subsystems 291 ================================== 292 293 DSA currently leverages the following subsystems: 294 295 - MDIO/PHY library: drivers/net/phy/phy.c, mdio_bus.c 296 - Switchdev: net/switchdev/* 297 - Device Tree for various of_* functions 298 299 MDIO/PHY library 300 ---------------- 301 302 Slave network devices exposed by DSA may or may not be interfacing with PHY 303 devices (struct phy_device as defined in include/linux/phy.h), but the DSA 304 subsystem deals with all possible combinations: 305 306 - internal PHY devices, built into the Ethernet switch hardware 307 - external PHY devices, connected via an internal or external MDIO bus 308 - internal PHY devices, connected via an internal MDIO bus 309 - special, non-autonegotiated or non MDIO-managed PHY devices: SFPs, MoCA; a.k.a 310 fixed PHYs 311 312 The PHY configuration is done by the dsa_slave_phy_setup() function and the 313 logic basically looks like this: 314 315 - if Device Tree is used, the PHY device is looked up using the standard 316 "phy-handle" property, if found, this PHY device is created and registered 317 using of_phy_connect() 318 319 - if Device Tree is used, and the PHY device is "fixed", that is, conforms to 320 the definition of a non-MDIO managed PHY as defined in 321 Documentation/devicetree/bindings/net/fixed-link.txt, the PHY is registered 322 and connected transparently using the special fixed MDIO bus driver 323 324 - finally, if the PHY is built into the switch, as is very common with 325 standalone switch packages, the PHY is probed using the slave MII bus created 326 by DSA 327 328 329 SWITCHDEV 330 --------- 331 332 DSA directly utilizes SWITCHDEV when interfacing with the bridge layer, and 333 more specifically with its VLAN filtering portion when configuring VLANs on top 334 of per-port slave network devices. Since DSA primarily deals with 335 MDIO-connected switches, although not exclusively, SWITCHDEV's 336 prepare/abort/commit phases are often simplified into a prepare phase which 337 checks whether the operation is supported by the DSA switch driver, and a commit 338 phase which applies the changes. 339 340 As of today, the only SWITCHDEV objects supported by DSA are the FDB and VLAN 341 objects. 342 343 Device Tree 344 ----------- 345 346 DSA features a standardized binding which is documented in 347 Documentation/devicetree/bindings/net/dsa/dsa.txt. PHY/MDIO library helper 348 functions such as of_get_phy_mode(), of_phy_connect() are also used to query 349 per-port PHY specific details: interface connection, MDIO bus location etc.. 350 351 Driver development 352 ================== 353 354 DSA switch drivers need to implement a dsa_switch_ops structure which will 355 contain the various members described below. 356 357 register_switch_driver() registers this dsa_switch_ops in its internal list 358 of drivers to probe for. unregister_switch_driver() does the exact opposite. 359 360 Unless requested differently by setting the priv_size member accordingly, DSA 361 does not allocate any driver private context space. 362 363 Switch configuration 364 -------------------- 365 366 - tag_protocol: this is to indicate what kind of tagging protocol is supported, 367 should be a valid value from the dsa_tag_protocol enum 368 369 - probe: probe routine which will be invoked by the DSA platform device upon 370 registration to test for the presence/absence of a switch device. For MDIO 371 devices, it is recommended to issue a read towards internal registers using 372 the switch pseudo-PHY and return whether this is a supported device. For other 373 buses, return a non-NULL string 374 375 - setup: setup function for the switch, this function is responsible for setting 376 up the dsa_switch_ops private structure with all it needs: register maps, 377 interrupts, mutexes, locks etc.. This function is also expected to properly 378 configure the switch to separate all network interfaces from each other, that 379 is, they should be isolated by the switch hardware itself, typically by creating 380 a Port-based VLAN ID for each port and allowing only the CPU port and the 381 specific port to be in the forwarding vector. Ports that are unused by the 382 platform should be disabled. Past this function, the switch is expected to be 383 fully configured and ready to serve any kind of request. It is recommended 384 to issue a software reset of the switch during this setup function in order to 385 avoid relying on what a previous software agent such as a bootloader/firmware 386 may have previously configured. 387 388 PHY devices and link management 389 ------------------------------- 390 391 - get_phy_flags: Some switches are interfaced to various kinds of Ethernet PHYs, 392 if the PHY library PHY driver needs to know about information it cannot obtain 393 on its own (e.g.: coming from switch memory mapped registers), this function 394 should return a 32-bits bitmask of "flags", that is private between the switch 395 driver and the Ethernet PHY driver in drivers/net/phy/*. 396 397 - phy_read: Function invoked by the DSA slave MDIO bus when attempting to read 398 the switch port MDIO registers. If unavailable, return 0xffff for each read. 399 For builtin switch Ethernet PHYs, this function should allow reading the link 400 status, auto-negotiation results, link partner pages etc.. 401 402 - phy_write: Function invoked by the DSA slave MDIO bus when attempting to write 403 to the switch port MDIO registers. If unavailable return a negative error 404 code. 405 406 - adjust_link: Function invoked by the PHY library when a slave network device 407 is attached to a PHY device. This function is responsible for appropriately 408 configuring the switch port link parameters: speed, duplex, pause based on 409 what the phy_device is providing. 410 411 - fixed_link_update: Function invoked by the PHY library, and specifically by 412 the fixed PHY driver asking the switch driver for link parameters that could 413 not be auto-negotiated, or obtained by reading the PHY registers through MDIO. 414 This is particularly useful for specific kinds of hardware such as QSGMII, 415 MoCA or other kinds of non-MDIO managed PHYs where out of band link 416 information is obtained 417 418 Ethtool operations 419 ------------------ 420 421 - get_strings: ethtool function used to query the driver's strings, will 422 typically return statistics strings, private flags strings etc. 423 424 - get_ethtool_stats: ethtool function used to query per-port statistics and 425 return their values. DSA overlays slave network devices general statistics: 426 RX/TX counters from the network device, with switch driver specific statistics 427 per port 428 429 - get_sset_count: ethtool function used to query the number of statistics items 430 431 - get_wol: ethtool function used to obtain Wake-on-LAN settings per-port, this 432 function may, for certain implementations also query the master network device 433 Wake-on-LAN settings if this interface needs to participate in Wake-on-LAN 434 435 - set_wol: ethtool function used to configure Wake-on-LAN settings per-port, 436 direct counterpart to set_wol with similar restrictions 437 438 - set_eee: ethtool function which is used to configure a switch port EEE (Green 439 Ethernet) settings, can optionally invoke the PHY library to enable EEE at the 440 PHY level if relevant. This function should enable EEE at the switch port MAC 441 controller and data-processing logic 442 443 - get_eee: ethtool function which is used to query a switch port EEE settings, 444 this function should return the EEE state of the switch port MAC controller 445 and data-processing logic as well as query the PHY for its currently configured 446 EEE settings 447 448 - get_eeprom_len: ethtool function returning for a given switch the EEPROM 449 length/size in bytes 450 451 - get_eeprom: ethtool function returning for a given switch the EEPROM contents 452 453 - set_eeprom: ethtool function writing specified data to a given switch EEPROM 454 455 - get_regs_len: ethtool function returning the register length for a given 456 switch 457 458 - get_regs: ethtool function returning the Ethernet switch internal register 459 contents. This function might require user-land code in ethtool to 460 pretty-print register values and registers 461 462 Power management 463 ---------------- 464 465 - suspend: function invoked by the DSA platform device when the system goes to 466 suspend, should quiesce all Ethernet switch activities, but keep ports 467 participating in Wake-on-LAN active as well as additional wake-up logic if 468 supported 469 470 - resume: function invoked by the DSA platform device when the system resumes, 471 should resume all Ethernet switch activities and re-configure the switch to be 472 in a fully active state 473 474 - port_enable: function invoked by the DSA slave network device ndo_open 475 function when a port is administratively brought up, this function should be 476 fully enabling a given switch port. DSA takes care of marking the port with 477 BR_STATE_BLOCKING if the port is a bridge member, or BR_STATE_FORWARDING if it 478 was not, and propagating these changes down to the hardware 479 480 - port_disable: function invoked by the DSA slave network device ndo_close 481 function when a port is administratively brought down, this function should be 482 fully disabling a given switch port. DSA takes care of marking the port with 483 BR_STATE_DISABLED and propagating changes to the hardware if this port is 484 disabled while being a bridge member 485 486 Bridge layer 487 ------------ 488 489 - port_bridge_join: bridge layer function invoked when a given switch port is 490 added to a bridge, this function should be doing the necessary at the switch 491 level to permit the joining port from being added to the relevant logical 492 domain for it to ingress/egress traffic with other members of the bridge. 493 494 - port_bridge_leave: bridge layer function invoked when a given switch port is 495 removed from a bridge, this function should be doing the necessary at the 496 switch level to deny the leaving port from ingress/egress traffic from the 497 remaining bridge members. When the port leaves the bridge, it should be aged 498 out at the switch hardware for the switch to (re) learn MAC addresses behind 499 this port. 500 501 - port_stp_state_set: bridge layer function invoked when a given switch port STP 502 state is computed by the bridge layer and should be propagated to switch 503 hardware to forward/block/learn traffic. The switch driver is responsible for 504 computing a STP state change based on current and asked parameters and perform 505 the relevant ageing based on the intersection results 506 507 Bridge VLAN filtering 508 --------------------- 509 510 - port_vlan_filtering: bridge layer function invoked when the bridge gets 511 configured for turning on or off VLAN filtering. If nothing specific needs to 512 be done at the hardware level, this callback does not need to be implemented. 513 When VLAN filtering is turned on, the hardware must be programmed with 514 rejecting 802.1Q frames which have VLAN IDs outside of the programmed allowed 515 VLAN ID map/rules. If there is no PVID programmed into the switch port, 516 untagged frames must be rejected as well. When turned off the switch must 517 accept any 802.1Q frames irrespective of their VLAN ID, and untagged frames are 518 allowed. 519 520 - port_vlan_prepare: bridge layer function invoked when the bridge prepares the 521 configuration of a VLAN on the given port. If the operation is not supported 522 by the hardware, this function should return -EOPNOTSUPP to inform the bridge 523 code to fallback to a software implementation. No hardware setup must be done 524 in this function. See port_vlan_add for this and details. 525 526 - port_vlan_add: bridge layer function invoked when a VLAN is configured 527 (tagged or untagged) for the given switch port 528 529 - port_vlan_del: bridge layer function invoked when a VLAN is removed from the 530 given switch port 531 532 - port_vlan_dump: bridge layer function invoked with a switchdev callback 533 function that the driver has to call for each VLAN the given port is a member 534 of. A switchdev object is used to carry the VID and bridge flags. 535 536 - port_fdb_prepare: bridge layer function invoked when the bridge prepares the 537 installation of a Forwarding Database entry. If the operation is not 538 supported, this function should return -EOPNOTSUPP to inform the bridge code 539 to fallback to a software implementation. No hardware setup must be done in 540 this function. See port_fdb_add for this and details. 541 542 - port_fdb_add: bridge layer function invoked when the bridge wants to install a 543 Forwarding Database entry, the switch hardware should be programmed with the 544 specified address in the specified VLAN Id in the forwarding database 545 associated with this VLAN ID 546 547 Note: VLAN ID 0 corresponds to the port private database, which, in the context 548 of DSA, would be the its port-based VLAN, used by the associated bridge device. 549 550 - port_fdb_del: bridge layer function invoked when the bridge wants to remove a 551 Forwarding Database entry, the switch hardware should be programmed to delete 552 the specified MAC address from the specified VLAN ID if it was mapped into 553 this port forwarding database 554 555 - port_fdb_dump: bridge layer function invoked with a switchdev callback 556 function that the driver has to call for each MAC address known to be behind 557 the given port. A switchdev object is used to carry the VID and FDB info. 558 559 - port_mdb_prepare: bridge layer function invoked when the bridge prepares the 560 installation of a multicast database entry. If the operation is not supported, 561 this function should return -EOPNOTSUPP to inform the bridge code to fallback 562 to a software implementation. No hardware setup must be done in this function. 563 See port_fdb_add for this and details. 564 565 - port_mdb_add: bridge layer function invoked when the bridge wants to install 566 a multicast database entry, the switch hardware should be programmed with the 567 specified address in the specified VLAN ID in the forwarding database 568 associated with this VLAN ID. 569 570 Note: VLAN ID 0 corresponds to the port private database, which, in the context 571 of DSA, would be the its port-based VLAN, used by the associated bridge device. 572 573 - port_mdb_del: bridge layer function invoked when the bridge wants to remove a 574 multicast database entry, the switch hardware should be programmed to delete 575 the specified MAC address from the specified VLAN ID if it was mapped into 576 this port forwarding database. 577 578 - port_mdb_dump: bridge layer function invoked with a switchdev callback 579 function that the driver has to call for each MAC address known to be behind 580 the given port. A switchdev object is used to carry the VID and MDB info. 581 582 TODO 583 ==== 584 585 Making SWITCHDEV and DSA converge towards an unified codebase 586 ------------------------------------------------------------- 587 588 SWITCHDEV properly takes care of abstracting the networking stack with offload 589 capable hardware, but does not enforce a strict switch device driver model. On 590 the other DSA enforces a fairly strict device driver model, and deals with most 591 of the switch specific. At some point we should envision a merger between these 592 two subsystems and get the best of both worlds. 593 594 Other hanging fruits 595 -------------------- 596 597 - making the number of ports fully dynamic and not dependent on DSA_MAX_PORTS 598 - allowing more than one CPU/management interface: 599 http://comments.gmane.org/gmane.linux.network/365657 600 - porting more drivers from other vendors: 601 http://comments.gmane.org/gmane.linux.network/365510