Loading drivers/net/ethernet/rocker/rocker.c +73 −0 Original line number Diff line number Diff line Loading @@ -3587,6 +3587,78 @@ static int rocker_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], return rocker_port_fdb(rocker_port, addr, vlan_id, flags); } static int rocker_fdb_fill_info(struct sk_buff *skb, struct rocker_port *rocker_port, const unsigned char *addr, u16 vid, u32 portid, u32 seq, int type, unsigned int flags) { struct nlmsghdr *nlh; struct ndmsg *ndm; nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); if (!nlh) return -EMSGSIZE; ndm = nlmsg_data(nlh); ndm->ndm_family = AF_BRIDGE; ndm->ndm_pad1 = 0; ndm->ndm_pad2 = 0; ndm->ndm_flags = NTF_SELF; ndm->ndm_type = 0; ndm->ndm_ifindex = rocker_port->dev->ifindex; ndm->ndm_state = NUD_REACHABLE; if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) goto nla_put_failure; if (vid && nla_put_u16(skb, NDA_VLAN, vid)) goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } static int rocker_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, struct net_device *filter_dev, int idx) { struct rocker_port *rocker_port = netdev_priv(dev); struct rocker *rocker = rocker_port->rocker; struct rocker_fdb_tbl_entry *found; struct hlist_node *tmp; int bkt; unsigned long lock_flags; const unsigned char *addr; u16 vid; int err; spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags); hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { if (found->key.lport != rocker_port->lport) continue; if (idx < cb->args[0]) goto skip; addr = found->key.addr; vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); err = rocker_fdb_fill_info(skb, rocker_port, addr, vid, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, NLM_F_MULTI); if (err < 0) break; skip: ++idx; } spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags); return idx; } static int rocker_port_switch_parent_id_get(struct net_device *dev, struct netdev_phys_item_id *psid) { Loading Loading @@ -3614,6 +3686,7 @@ static const struct net_device_ops rocker_port_netdev_ops = { .ndo_vlan_rx_kill_vid = rocker_port_vlan_rx_kill_vid, .ndo_fdb_add = rocker_port_fdb_add, .ndo_fdb_del = rocker_port_fdb_del, .ndo_fdb_dump = rocker_port_fdb_dump, .ndo_switch_parent_id_get = rocker_port_switch_parent_id_get, .ndo_switch_port_stp_update = rocker_port_switch_port_stp_update, }; Loading Loading
drivers/net/ethernet/rocker/rocker.c +73 −0 Original line number Diff line number Diff line Loading @@ -3587,6 +3587,78 @@ static int rocker_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], return rocker_port_fdb(rocker_port, addr, vlan_id, flags); } static int rocker_fdb_fill_info(struct sk_buff *skb, struct rocker_port *rocker_port, const unsigned char *addr, u16 vid, u32 portid, u32 seq, int type, unsigned int flags) { struct nlmsghdr *nlh; struct ndmsg *ndm; nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags); if (!nlh) return -EMSGSIZE; ndm = nlmsg_data(nlh); ndm->ndm_family = AF_BRIDGE; ndm->ndm_pad1 = 0; ndm->ndm_pad2 = 0; ndm->ndm_flags = NTF_SELF; ndm->ndm_type = 0; ndm->ndm_ifindex = rocker_port->dev->ifindex; ndm->ndm_state = NUD_REACHABLE; if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr)) goto nla_put_failure; if (vid && nla_put_u16(skb, NDA_VLAN, vid)) goto nla_put_failure; return nlmsg_end(skb, nlh); nla_put_failure: nlmsg_cancel(skb, nlh); return -EMSGSIZE; } static int rocker_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev, struct net_device *filter_dev, int idx) { struct rocker_port *rocker_port = netdev_priv(dev); struct rocker *rocker = rocker_port->rocker; struct rocker_fdb_tbl_entry *found; struct hlist_node *tmp; int bkt; unsigned long lock_flags; const unsigned char *addr; u16 vid; int err; spin_lock_irqsave(&rocker->fdb_tbl_lock, lock_flags); hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { if (found->key.lport != rocker_port->lport) continue; if (idx < cb->args[0]) goto skip; addr = found->key.addr; vid = rocker_port_vlan_to_vid(rocker_port, found->key.vlan_id); err = rocker_fdb_fill_info(skb, rocker_port, addr, vid, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, NLM_F_MULTI); if (err < 0) break; skip: ++idx; } spin_unlock_irqrestore(&rocker->fdb_tbl_lock, lock_flags); return idx; } static int rocker_port_switch_parent_id_get(struct net_device *dev, struct netdev_phys_item_id *psid) { Loading Loading @@ -3614,6 +3686,7 @@ static const struct net_device_ops rocker_port_netdev_ops = { .ndo_vlan_rx_kill_vid = rocker_port_vlan_rx_kill_vid, .ndo_fdb_add = rocker_port_fdb_add, .ndo_fdb_del = rocker_port_fdb_del, .ndo_fdb_dump = rocker_port_fdb_dump, .ndo_switch_parent_id_get = rocker_port_switch_parent_id_get, .ndo_switch_port_stp_update = rocker_port_switch_port_stp_update, }; Loading