lldpad/lldpad-0.9.41-lldpad-add-802.1Qaz-nlmsg-set-query-support.patch
2011-04-21 09:10:21 +02:00

324 lines
8.0 KiB
Diff

From fa0230ed0e11d5a5a07dda1d4c882f1272e5c5b8 Mon Sep 17 00:00:00 2001
From: John Fastabend <john.r.fastabend@intel.com>
Date: Wed, 6 Apr 2011 08:48:06 -0700
Subject: [PATCH 43/51] lldpad: add 802.1Qaz nlmsg set/query support
This adds support to nltest for 8021Qaz set and query
of ETS, PFC, and APP.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: Petr Sabata <psabata@redhat.com>
---
nltest.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 247 insertions(+), 2 deletions(-)
diff --git a/nltest.c b/nltest.c
index 6a00d74..d937064 100644
--- a/nltest.c
+++ b/nltest.c
@@ -48,10 +48,13 @@ static void hexprint(char *b, int len)
}
#endif
+#define NLMSG_TAIL(nmsg) \
+ ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+
static int init_socket(void)
{
int sd;
- int rcv_size;
+ int rcv_size = 8 * 1024;
struct sockaddr_nl snl;
sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -116,6 +119,56 @@ static struct nlmsghdr *start_msg(__u16 msg_type, __u8 arg)
}
+int addattr_l(struct nlmsghdr *n, int type, const void *data,
+ int alen)
+{
+ int len = RTA_LENGTH(alen);
+ struct rtattr *rta;
+
+ if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > MAX_MSG_SIZE) {
+ fprintf(stderr, "addattr_l: message exceeded bound of %d\n",
+ MAX_MSG_SIZE);
+ return -1;
+ }
+ rta = NLMSG_TAIL(n);
+ rta->rta_type = type;
+ rta->rta_len = len;
+ memcpy(RTA_DATA(rta), data, alen);
+ n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
+ return 0;
+}
+
+struct rtattr *addattr_nest(struct nlmsghdr *n, int type)
+{
+ struct rtattr *nest = NLMSG_TAIL(n);
+
+ addattr_l(n, type, NULL, 0);
+ return nest;
+}
+
+int addattr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
+{
+ nest->rta_len = (void *)NLMSG_TAIL(n) - (void *)nest;
+ return n->nlmsg_len;
+}
+
+int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
+ tb[rta->rta_type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+ if (len)
+ fprintf(stderr, "!!!Deficit %d, rta_len=%d\n",
+ len, rta->rta_len);
+ return 0;
+}
+
+#define parse_rtattr_nested(tb, max, rta) \
+ (parse_rtattr((tb), (max), RTA_DATA(rta), RTA_PAYLOAD(rta)))
+
static struct rtattr *add_rta(struct nlmsghdr *nlh, __u16 rta_type,
void *attr, __u16 rta_len)
{
@@ -172,8 +225,8 @@ static struct nlmsghdr *get_msg(void)
if ((nlh->nlmsg_type == NLMSG_ERROR) || (len < 0) ||
!(NLMSG_OK(nlh, (unsigned int)len))) {
free(nlh);
-#ifdef HEXDUMP
printf("RECEIVE FAILED: %d\n", len);
+#ifdef HEXDUMP
if (len > 0)
hexprint((char *)nlh, len);
#endif
@@ -535,6 +588,7 @@ static int get_cap(char *ifname, __u8 *cap)
"would sure be nice.\n");
return -EIO;
}
+
rta_child = NLA_DATA(rta_parent);
rta_parent = (struct rtattr *)((char *)rta_parent +
NLMSG_ALIGN(rta_parent->rta_len));
@@ -570,6 +624,9 @@ static int get_cap(char *ifname, __u8 *cap)
case DCB_CAP_ATTR_BCN:
printf("bcn: ");
break;
+ case DCB_CAP_ATTR_DCBX:
+ printf("dcbx: ");
+ break;
default:
printf("unknown type: ");
break;
@@ -1081,6 +1138,178 @@ int set_hw_app0(char *ifname, appgroup_attribs *app_data)
}
#endif /* DCB_APP_DRV_IF_SUPPORTED */
+void print_app(struct rtattr *app_attr)
+{
+ struct dcb_app *data;
+
+ data = RTA_DATA(app_attr);
+ printf("selector %i protocol %i priority %i\n",
+ data->selector, data->protocol, data->priority);
+}
+
+void print_pfc(struct ieee_pfc *pfc)
+{
+ int i;
+ printf("PFC:\n");
+ printf("\t cap %2x en %2x\n", pfc->pfc_cap, pfc->pfc_en);
+ printf("\t mbc %2x delay %i\n", pfc->mbc, pfc->delay);
+
+ printf("\t requests: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", pfc->requests[i]);
+ printf("\n");
+
+ printf("\t requests: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", pfc->indications[i]);
+ printf("\n");
+}
+
+void print_ets(struct ieee_ets *ets)
+{
+ int i;
+ printf("ETS:\n");
+ printf("\tcap %2x cbs %2x\n", ets->ets_cap, ets->cbs);
+
+ printf("\tets tc_tx_bw: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->tc_tx_bw[i]);
+ printf("\n");
+
+ printf("\tets tc_rx_bw: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->tc_rx_bw[i]);
+ printf("\n");
+
+ printf("\tets tc_tsa: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->tc_tsa[i]);
+ printf("\n");
+
+ printf("\tets prio_tc: ");
+ for (i = 0; i < 8; i++)
+ printf("%i ", ets->prio_tc[i]);
+ printf("\n");
+}
+
+int set_ieee(char *ifname, struct ieee_ets *ets_data, struct ieee_pfc *pfc_data,
+ struct dcb_app *app_data)
+{
+ struct nlmsghdr *nlh;
+ struct rtattr *ieee, *apptbl;
+
+ nlh = start_msg(RTM_SETDCB, DCB_CMD_IEEE_SET);
+ if (NULL == nlh)
+ return -EIO;
+
+ addattr_l(nlh, DCB_ATTR_IFNAME, ifname, strlen(ifname) + 1);
+ ieee = addattr_nest(nlh, DCB_ATTR_IEEE);
+ if (ets_data)
+ addattr_l(nlh, DCB_ATTR_IEEE_ETS, ets_data, sizeof(*ets_data));
+ if (pfc_data)
+ addattr_l(nlh, DCB_ATTR_IEEE_PFC, pfc_data, sizeof(*pfc_data));
+ if (app_data) {
+ apptbl = addattr_nest(nlh, DCB_ATTR_IEEE_APP_TABLE);
+ addattr_l(nlh, DCB_ATTR_IEEE_APP, app_data, sizeof(*app_data));
+#if 1
+ app_data->protocol++;
+ addattr_l(nlh, DCB_ATTR_IEEE_APP, app_data, sizeof(*app_data));
+#endif
+ addattr_nest_end(nlh, apptbl);
+ }
+ addattr_nest_end(nlh, ieee);
+
+ if (send_msg(nlh))
+ return -EIO;
+
+ return recv_msg(DCB_CMD_IEEE_SET, DCB_ATTR_IEEE);
+}
+
+#define DCB_RTA(r) \
+ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct dcbmsg))))
+
+int get_ieee(char *ifname)
+{
+ struct nlmsghdr *nlh;
+ struct dcbmsg *d;
+ struct rtattr *dcb, *ieee[DCB_ATTR_IEEE_MAX+1];
+ struct rtattr *tb[DCB_ATTR_MAX + 1];
+ int len;
+
+ nlh = start_msg(RTM_GETDCB, DCB_CMD_IEEE_GET);
+ if (NULL == nlh) {
+ printf("start_msg failed\n");
+ return -EIO;
+ }
+
+ addattr_l(nlh, DCB_ATTR_IFNAME, ifname, strlen(ifname) + 1);
+ if (send_msg(nlh)) {
+ printf("send failure\n");
+ return -EIO;
+ }
+
+ /* Receive 802.1Qaz parameters */
+ memset(nlh, 0, MAX_MSG_SIZE);
+ len = recv(nl_sd, (void *)nlh, MAX_MSG_SIZE, 0);
+ if (len < 0) {
+ perror("ieee_get");
+ return -EIO;
+ }
+
+ if (nlh->nlmsg_type != RTM_GETDCB) {
+ struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA(nlh);
+ if (nlh->nlmsg_type == NLMSG_ERROR) {
+ printf("NLMSG_ERROR: err(%i): %s\n",
+ err->error, strerror(err->error * -1));
+ }
+ return -1;
+ }
+
+ d = NLMSG_DATA(nlh);
+ len -= NLMSG_LENGTH(sizeof(*d));
+ if (len < 0) {
+ printf("Broken message\n");
+ return -1;
+ }
+
+ parse_rtattr(tb, DCB_ATTR_MAX, DCB_RTA(d), len);
+ if (!tb[DCB_ATTR_IEEE]) {
+ printf("Missing DCB_ATTR_IEEE attribute!\n");
+ return -1;
+ }
+
+ if (tb[DCB_ATTR_IFNAME]) {
+ printf("\tifname %s\n", RTA_DATA(tb[DCB_ATTR_IFNAME]));
+ } else {
+ printf("Missing DCB_ATTR_IFNAME attribute!\n");
+ return -1;
+ }
+
+ dcb = tb[DCB_ATTR_IEEE];
+ parse_rtattr_nested(ieee, DCB_ATTR_IEEE_MAX, dcb);
+ if (ieee[DCB_ATTR_IEEE_ETS]) {
+ struct ieee_ets *ets = RTA_DATA(ieee[DCB_ATTR_IEEE_ETS]);
+ print_ets(ets);
+ }
+
+ if (ieee[DCB_ATTR_IEEE_PFC]) {
+ struct ieee_pfc *pfc = RTA_DATA(ieee[DCB_ATTR_IEEE_PFC]);
+ print_pfc(pfc);
+ }
+
+ if (ieee[DCB_ATTR_IEEE_APP_TABLE]) {
+ struct rtattr *i, *app_list = ieee[DCB_ATTR_IEEE_APP_TABLE];
+ int rem = RTA_PAYLOAD(app_list);
+ printf("APP: %i\n");
+ for (i = RTA_DATA(app_list);
+ RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem))
+ print_app(i);
+ }
+
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct tc_config tc[8];
@@ -1285,6 +1514,22 @@ int main(int argc, char *argv[])
printf("GETTING APP FAILED!.\n");
}
#endif /* DCB_APP_DRV_IF_SUPPORTED */
+
+ if (1) {
+ printf("\nSETTING ETS:\n");
+ struct ieee_ets ets = { 0, 0x1, 0,
+ {25, 25, 25, 25, 0, 0, 0, 0},
+ {0, 0, 0, 0, 25, 25, 25, 25},
+ {1, 2, 3, 4, 1, 2, 3, 4},
+ {1, 2, 3, 4, 1, 2, 3, 4} };
+ struct ieee_pfc pfc = {0xf1, 0, 0, 0x32};
+ struct dcb_app app = {0, 0x8906, 4};
+
+ set_ieee(argv[1], &ets, &pfc, &app);
+ }
+
+ get_ieee(argv[1]);
+
err_main:
close(nl_sd);
return err;
--
1.7.4.4