diff options
Diffstat (limited to 'net/dcb/dcbnl.c')
-rw-r--r-- | net/dcb/dcbnl.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 8379496de82b..e0879bfb7dd5 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -64,6 +64,7 @@ static struct nla_policy dcbnl_rtnl_policy[DCB_ATTR_MAX + 1] = { | |||
64 | [DCB_ATTR_CAP] = {.type = NLA_NESTED}, | 64 | [DCB_ATTR_CAP] = {.type = NLA_NESTED}, |
65 | [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, | 65 | [DCB_ATTR_PFC_STATE] = {.type = NLA_U8}, |
66 | [DCB_ATTR_BCN] = {.type = NLA_NESTED}, | 66 | [DCB_ATTR_BCN] = {.type = NLA_NESTED}, |
67 | [DCB_ATTR_APP] = {.type = NLA_NESTED}, | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | /* DCB priority flow control to User Priority nested attributes */ | 70 | /* DCB priority flow control to User Priority nested attributes */ |
@@ -158,6 +159,13 @@ static struct nla_policy dcbnl_bcn_nest[DCB_BCN_ATTR_MAX + 1] = { | |||
158 | [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG}, | 159 | [DCB_BCN_ATTR_ALL] = {.type = NLA_FLAG}, |
159 | }; | 160 | }; |
160 | 161 | ||
162 | /* DCB APP nested attributes. */ | ||
163 | static struct nla_policy dcbnl_app_nest[DCB_APP_ATTR_MAX + 1] = { | ||
164 | [DCB_APP_ATTR_IDTYPE] = {.type = NLA_U8}, | ||
165 | [DCB_APP_ATTR_ID] = {.type = NLA_U16}, | ||
166 | [DCB_APP_ATTR_PRIORITY] = {.type = NLA_U8}, | ||
167 | }; | ||
168 | |||
161 | /* standard netlink reply call */ | 169 | /* standard netlink reply call */ |
162 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, | 170 | static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, |
163 | u32 seq, u16 flags) | 171 | u32 seq, u16 flags) |
@@ -536,6 +544,120 @@ static int dcbnl_setpfcstate(struct net_device *netdev, struct nlattr **tb, | |||
536 | return ret; | 544 | return ret; |
537 | } | 545 | } |
538 | 546 | ||
547 | static int dcbnl_getapp(struct net_device *netdev, struct nlattr **tb, | ||
548 | u32 pid, u32 seq, u16 flags) | ||
549 | { | ||
550 | struct sk_buff *dcbnl_skb; | ||
551 | struct nlmsghdr *nlh; | ||
552 | struct dcbmsg *dcb; | ||
553 | struct nlattr *app_nest; | ||
554 | struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; | ||
555 | u16 id; | ||
556 | u8 up, idtype; | ||
557 | int ret = -EINVAL; | ||
558 | |||
559 | if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->getapp) | ||
560 | goto out; | ||
561 | |||
562 | ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], | ||
563 | dcbnl_app_nest); | ||
564 | if (ret) | ||
565 | goto out; | ||
566 | |||
567 | ret = -EINVAL; | ||
568 | /* all must be non-null */ | ||
569 | if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || | ||
570 | (!app_tb[DCB_APP_ATTR_ID])) | ||
571 | goto out; | ||
572 | |||
573 | /* either by eth type or by socket number */ | ||
574 | idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); | ||
575 | if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && | ||
576 | (idtype != DCB_APP_IDTYPE_PORTNUM)) | ||
577 | goto out; | ||
578 | |||
579 | id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); | ||
580 | up = netdev->dcbnl_ops->getapp(netdev, idtype, id); | ||
581 | |||
582 | /* send this back */ | ||
583 | dcbnl_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
584 | if (!dcbnl_skb) | ||
585 | goto out; | ||
586 | |||
587 | nlh = NLMSG_NEW(dcbnl_skb, pid, seq, RTM_GETDCB, sizeof(*dcb), flags); | ||
588 | dcb = NLMSG_DATA(nlh); | ||
589 | dcb->dcb_family = AF_UNSPEC; | ||
590 | dcb->cmd = DCB_CMD_GAPP; | ||
591 | |||
592 | app_nest = nla_nest_start(dcbnl_skb, DCB_ATTR_APP); | ||
593 | ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_IDTYPE, idtype); | ||
594 | if (ret) | ||
595 | goto out_cancel; | ||
596 | |||
597 | ret = nla_put_u16(dcbnl_skb, DCB_APP_ATTR_ID, id); | ||
598 | if (ret) | ||
599 | goto out_cancel; | ||
600 | |||
601 | ret = nla_put_u8(dcbnl_skb, DCB_APP_ATTR_PRIORITY, up); | ||
602 | if (ret) | ||
603 | goto out_cancel; | ||
604 | |||
605 | nla_nest_end(dcbnl_skb, app_nest); | ||
606 | nlmsg_end(dcbnl_skb, nlh); | ||
607 | |||
608 | ret = rtnl_unicast(dcbnl_skb, &init_net, pid); | ||
609 | if (ret) | ||
610 | goto nlmsg_failure; | ||
611 | |||
612 | goto out; | ||
613 | |||
614 | out_cancel: | ||
615 | nla_nest_cancel(dcbnl_skb, app_nest); | ||
616 | nlmsg_failure: | ||
617 | kfree_skb(dcbnl_skb); | ||
618 | out: | ||
619 | return ret; | ||
620 | } | ||
621 | |||
622 | static int dcbnl_setapp(struct net_device *netdev, struct nlattr **tb, | ||
623 | u32 pid, u32 seq, u16 flags) | ||
624 | { | ||
625 | int ret = -EINVAL; | ||
626 | u16 id; | ||
627 | u8 up, idtype; | ||
628 | struct nlattr *app_tb[DCB_APP_ATTR_MAX + 1]; | ||
629 | |||
630 | if (!tb[DCB_ATTR_APP] || !netdev->dcbnl_ops->setapp) | ||
631 | goto out; | ||
632 | |||
633 | ret = nla_parse_nested(app_tb, DCB_APP_ATTR_MAX, tb[DCB_ATTR_APP], | ||
634 | dcbnl_app_nest); | ||
635 | if (ret) | ||
636 | goto out; | ||
637 | |||
638 | ret = -EINVAL; | ||
639 | /* all must be non-null */ | ||
640 | if ((!app_tb[DCB_APP_ATTR_IDTYPE]) || | ||
641 | (!app_tb[DCB_APP_ATTR_ID]) || | ||
642 | (!app_tb[DCB_APP_ATTR_PRIORITY])) | ||
643 | goto out; | ||
644 | |||
645 | /* either by eth type or by socket number */ | ||
646 | idtype = nla_get_u8(app_tb[DCB_APP_ATTR_IDTYPE]); | ||
647 | if ((idtype != DCB_APP_IDTYPE_ETHTYPE) && | ||
648 | (idtype != DCB_APP_IDTYPE_PORTNUM)) | ||
649 | goto out; | ||
650 | |||
651 | id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); | ||
652 | up = nla_get_u8(app_tb[DCB_APP_ATTR_PRIORITY]); | ||
653 | |||
654 | ret = dcbnl_reply(netdev->dcbnl_ops->setapp(netdev, idtype, id, up), | ||
655 | RTM_SETDCB, DCB_CMD_SAPP, DCB_ATTR_APP, | ||
656 | pid, seq, flags); | ||
657 | out: | ||
658 | return ret; | ||
659 | } | ||
660 | |||
539 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, | 661 | static int __dcbnl_pg_getcfg(struct net_device *netdev, struct nlattr **tb, |
540 | u32 pid, u32 seq, u16 flags, int dir) | 662 | u32 pid, u32 seq, u16 flags, int dir) |
541 | { | 663 | { |
@@ -1093,6 +1215,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1093 | ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, | 1215 | ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq, |
1094 | nlh->nlmsg_flags); | 1216 | nlh->nlmsg_flags); |
1095 | goto out; | 1217 | goto out; |
1218 | case DCB_CMD_GAPP: | ||
1219 | ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq, | ||
1220 | nlh->nlmsg_flags); | ||
1221 | goto out; | ||
1222 | case DCB_CMD_SAPP: | ||
1223 | ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq, | ||
1224 | nlh->nlmsg_flags); | ||
1225 | goto out; | ||
1096 | default: | 1226 | default: |
1097 | goto errout; | 1227 | goto errout; |
1098 | } | 1228 | } |