static int iplink_parse_vf(int vf, int *argcp, char ***argvp, struct iplink_req *req, int dev_index) { char new_rate_api = 0, count = 0, override_legacy_rate = 0; struct ifla_vf_rate tivt; int len, argc = *argcp; char **argv = *argvp; struct rtattr *vfinfo; tivt.min_tx_rate = -1; tivt.max_tx_rate = -1; vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO); while (NEXT_ARG_OK()) { NEXT_ARG(); count++; if (!matches(*argv, "max_tx_rate")) { /* new API in use */ new_rate_api = 1; /* override legacy rate */ override_legacy_rate = 1; } else if (!matches(*argv, "min_tx_rate")) { /* new API in use */ new_rate_api = 1; } } while (count--) { /* rewind arg */ PREV_ARG(); } while (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "mac") == 0) { struct ifla_vf_mac ivm; NEXT_ARG(); ivm.vf = vf; len = ll_addr_a2n((char *)ivm.mac, 32, *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm)); } else if (matches(*argv, "vlan") == 0) { struct ifla_vf_vlan ivv; NEXT_ARG(); if (get_unsigned(&ivv.vlan, *argv, 0)) { invarg("Invalid \"vlan\" value\n", *argv); } ivv.vf = vf; ivv.qos = 0; if (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "qos") == 0) { NEXT_ARG(); if (get_unsigned(&ivv.qos, *argv, 0)) { invarg("Invalid \"qos\" value\n", *argv); } } else { /* rewind arg */ PREV_ARG(); } } addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv)); } else if (matches(*argv, "rate") == 0) { struct ifla_vf_tx_rate ivt; NEXT_ARG(); if (get_unsigned(&ivt.rate, *argv, 0)) { invarg("Invalid \"rate\" value\n", *argv); } ivt.vf = vf; if (!new_rate_api) addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); else if (!override_legacy_rate) tivt.max_tx_rate = ivt.rate; } else if (matches(*argv, "max_tx_rate") == 0) { NEXT_ARG(); if (get_unsigned(&tivt.max_tx_rate, *argv, 0)) invarg("Invalid \"max tx rate\" value\n", *argv); tivt.vf = vf; } else if (matches(*argv, "min_tx_rate") == 0) { NEXT_ARG(); if (get_unsigned(&tivt.min_tx_rate, *argv, 0)) invarg("Invalid \"min tx rate\" value\n", *argv); tivt.vf = vf; } else if (matches(*argv, "spoofchk") == 0) { struct ifla_vf_spoofchk ivs; NEXT_ARG(); if (matches(*argv, "on") == 0) ivs.setting = 1; else if (matches(*argv, "off") == 0) ivs.setting = 0; else invarg("Invalid \"spoofchk\" value\n", *argv); ivs.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs)); } else if (matches(*argv, "state") == 0) { struct ifla_vf_link_state ivl; NEXT_ARG(); if (matches(*argv, "auto") == 0) ivl.link_state = IFLA_VF_LINK_STATE_AUTO; else if (matches(*argv, "enable") == 0) ivl.link_state = IFLA_VF_LINK_STATE_ENABLE; else if (matches(*argv, "disable") == 0) ivl.link_state = IFLA_VF_LINK_STATE_DISABLE; else invarg("Invalid \"state\" value\n", *argv); ivl.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_LINK_STATE, &ivl, sizeof(ivl)); } else { /* rewind arg */ PREV_ARG(); break; } } if (new_rate_api) { int tmin, tmax; if (tivt.min_tx_rate == -1 || tivt.max_tx_rate == -1) { ipaddr_get_vf_rate(tivt.vf, &tmin, &tmax, dev_index); if (tivt.min_tx_rate == -1) tivt.min_tx_rate = tmin; if (tivt.max_tx_rate == -1) tivt.max_tx_rate = tmax; } addattr_l(&req->n, sizeof(*req), IFLA_VF_RATE, &tivt, sizeof(tivt)); } if (argc == *argcp) incomplete_command(); addattr_nest_end(&req->n, vfinfo); *argcp = argc; *argvp = argv; return 0; }
static int iplink_parse_vf(int vf, int *argcp, char ***argvp, struct iplink_req *req) { int len, argc = *argcp; char **argv = *argvp; struct rtattr *vfinfo; vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO); while (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "mac") == 0) { struct ifla_vf_mac ivm; NEXT_ARG(); ivm.vf = vf; len = ll_addr_a2n((char *)ivm.mac, 32, *argv); if (len < 0) return -1; addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm, sizeof(ivm)); } else if (matches(*argv, "vlan") == 0) { struct ifla_vf_vlan ivv; NEXT_ARG(); if (get_unsigned(&ivv.vlan, *argv, 0)) { invarg("Invalid \"vlan\" value\n", *argv); } ivv.vf = vf; ivv.qos = 0; if (NEXT_ARG_OK()) { NEXT_ARG(); if (matches(*argv, "qos") == 0) { NEXT_ARG(); if (get_unsigned(&ivv.qos, *argv, 0)) { invarg("Invalid \"qos\" value\n", *argv); } } else { /* rewind arg */ PREV_ARG(); } } addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv, sizeof(ivv)); } else if (matches(*argv, "rate") == 0) { struct ifla_vf_tx_rate ivt; NEXT_ARG(); if (get_unsigned(&ivt.rate, *argv, 0)) { invarg("Invalid \"rate\" value\n", *argv); } ivt.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt, sizeof(ivt)); } else if (matches(*argv, "spoofchk") == 0) { struct ifla_vf_spoofchk ivs; NEXT_ARG(); if (matches(*argv, "on") == 0) ivs.setting = 1; else if (matches(*argv, "off") == 0) ivs.setting = 0; else invarg("Invalid \"spoofchk\" value\n", *argv); ivs.vf = vf; addattr_l(&req->n, sizeof(*req), IFLA_VF_SPOOFCHK, &ivs, sizeof(ivs)); } else { /* rewind arg */ PREV_ARG(); break; } } if (argc == *argcp) incomplete_command(); addattr_nest_end(&req->n, vfinfo); *argcp = argc; *argvp = argv; return 0; }