dataplane.c (3819B)
1 // Broadcom XGS dataplane backend for linkd. 2 // 3 // Built and shipped by the `openbcm` package, NOT by the linkd build. It is a 4 // plugin precisely so that a single OS image runs unchanged on hardware with 5 // and without a switching ASIC: on a Broadcom box the openbcm package drops 6 // this object into LINKD_DATAPLANE_DIR, everywhere else the directory stays 7 // empty and linkd falls back to the built-in kernel backend. 8 // 9 // Building this requires the OpenBCM SDK headers and libbcm. See the README 10 // next to this file. 11 12 #include <stdio.h> 13 #include <unistd.h> 14 15 #include "dataplane.h" 16 17 // The BDE character device is created by the openbcm kernel modules once they 18 // have enumerated a switch ASIC over PCIe. Its presence is the cheapest 19 // reliable signal that this backend can drive the box. 20 #define BCM_BDE_DEV "/dev/linux-kernel-bde" 21 22 static int bcm_probe(void) { 23 if (access(BCM_BDE_DEV, F_OK) != 0) return DP_RET_ERROR; 24 return DP_RET_OK; 25 } 26 27 static int bcm_init(void) { 28 // TODO: SDK bring-up. 29 // - read the board config (config.bcm) for the port/SerDes map 30 // - soc_cm_device_create / attach unit 0 31 // - run the board init sequence 32 // - create KNET netdevs (swpN) for each front-panel port 33 fprintf(stderr, "dataplane/bcm: SDK bring-up not implemented\n"); 34 return DP_RET_ERROR; 35 } 36 37 static void bcm_fini(void) { 38 // TODO: detach unit, tear down KNET netdevs 39 } 40 41 static int bcm_port_apply(const struct dp_port *port) { 42 // TODO: bcm_port_speed_set / bcm_port_autoneg_set, and 43 // bcm_port_phy_control_set for FEC 44 (void)port; 45 return DP_RET_ERROR; 46 } 47 48 static int bcm_port_admin(const char *ifname, bool up) { 49 // TODO: bcm_port_enable_set 50 (void)ifname; 51 (void)up; 52 return DP_RET_ERROR; 53 } 54 55 static int bcm_port_mtu(const char *ifname, uint32_t mtu) { 56 // TODO: bcm_port_frame_max_set. Driven by the netlink mirror so the ASIC 57 // frame limit tracks whatever ifupdown put on the netdev. 58 (void)ifname; 59 (void)mtu; 60 return DP_RET_ERROR; 61 } 62 63 static int bcm_rif_add(const struct dp_rif *rif) { 64 // TODO: bcm_l3_intf_create, keyed by rif->table for per-VRF LPM 65 (void)rif; 66 return DP_RET_ERROR; 67 } 68 69 static int bcm_rif_del(const struct dp_rif *rif) { 70 // TODO: bcm_l3_intf_delete, keyed by rif->table 71 (void)rif; 72 return DP_RET_ERROR; 73 } 74 75 static int bcm_neigh_add(const struct dp_neigh *neigh) { 76 // TODO: bcm_l3_host_add, keyed by neigh->table 77 (void)neigh; 78 return DP_RET_ERROR; 79 } 80 81 static int bcm_neigh_del(const struct dp_neigh *neigh) { 82 // TODO: bcm_l3_host_delete, keyed by neigh->table 83 (void)neigh; 84 return DP_RET_ERROR; 85 } 86 87 static int bcm_route_add(const struct dp_route *route) { 88 // TODO: bcm_l3_route_add with vrf context from route->table; for nh_count > 1 89 // build a bcm_l3_egress_ecmp group and refcount it per table across 90 // routes sharing the same nexthop set 91 (void)route; 92 return DP_RET_ERROR; 93 } 94 95 static int bcm_route_del(const struct dp_route *route) { 96 // TODO: bcm_l3_route_delete with vrf context from route->table, release ECMP 97 // group when refcount hits zero 98 (void)route; 99 return DP_RET_ERROR; 100 } 101 102 static int bcm_resync(void) { 103 // TODO: walk the ASIC tables, diff against the kernel, converge. 104 // Netlink drops messages under load, so this is the correctness backstop, 105 // not an optimisation. 106 return DP_RET_ERROR; 107 } 108 109 struct dp_ops linkd_dataplane_ops = { 110 .abi = LINKD_DATAPLANE_ABI, 111 .name = "bcm", 112 .probe = bcm_probe, 113 .init = bcm_init, 114 .fini = bcm_fini, 115 .port_apply = bcm_port_apply, 116 .port_admin = bcm_port_admin, 117 .port_mtu = bcm_port_mtu, 118 .rif_add = bcm_rif_add, 119 .rif_del = bcm_rif_del, 120 .neigh_add = bcm_neigh_add, 121 .neigh_del = bcm_neigh_del, 122 .route_add = bcm_route_add, 123 .route_del = bcm_route_del, 124 .resync = bcm_resync, 125 };