0001
0002
0003 #include <linux/ethtool_netlink.h>
0004 #include <linux/bitmap.h>
0005 #include "netlink.h"
0006 #include "bitset.h"
0007
0008
0009
0010
0011
0012
0013
0014
0015 static u32 ethnl_lower_bits(unsigned int n)
0016 {
0017 return ~(u32)0 >> (32 - n % 32);
0018 }
0019
0020 static u32 ethnl_upper_bits(unsigned int n)
0021 {
0022 return ~(u32)0 << (n % 32);
0023 }
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 static void ethnl_bitmap32_clear(u32 *dst, unsigned int start, unsigned int end,
0035 bool *mod)
0036 {
0037 unsigned int start_word = start / 32;
0038 unsigned int end_word = end / 32;
0039 unsigned int i;
0040 u32 mask;
0041
0042 if (end <= start)
0043 return;
0044
0045 if (start % 32) {
0046 mask = ethnl_upper_bits(start);
0047 if (end_word == start_word) {
0048 mask &= ethnl_lower_bits(end);
0049 if (dst[start_word] & mask) {
0050 dst[start_word] &= ~mask;
0051 *mod = true;
0052 }
0053 return;
0054 }
0055 if (dst[start_word] & mask) {
0056 dst[start_word] &= ~mask;
0057 *mod = true;
0058 }
0059 start_word++;
0060 }
0061
0062 for (i = start_word; i < end_word; i++) {
0063 if (dst[i]) {
0064 dst[i] = 0;
0065 *mod = true;
0066 }
0067 }
0068 if (end % 32) {
0069 mask = ethnl_lower_bits(end);
0070 if (dst[end_word] & mask) {
0071 dst[end_word] &= ~mask;
0072 *mod = true;
0073 }
0074 }
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 static bool ethnl_bitmap32_not_zero(const u32 *map, unsigned int start,
0087 unsigned int end)
0088 {
0089 unsigned int start_word = start / 32;
0090 unsigned int end_word = end / 32;
0091 u32 mask;
0092
0093 if (end <= start)
0094 return true;
0095
0096 if (start % 32) {
0097 mask = ethnl_upper_bits(start);
0098 if (end_word == start_word) {
0099 mask &= ethnl_lower_bits(end);
0100 return map[start_word] & mask;
0101 }
0102 if (map[start_word] & mask)
0103 return true;
0104 start_word++;
0105 }
0106
0107 if (!memchr_inv(map + start_word, '\0',
0108 (end_word - start_word) * sizeof(u32)))
0109 return true;
0110 if (end % 32 == 0)
0111 return true;
0112 return map[end_word] & ethnl_lower_bits(end);
0113 }
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128 static void ethnl_bitmap32_update(u32 *dst, unsigned int nbits,
0129 const u32 *value, const u32 *mask, bool *mod)
0130 {
0131 while (nbits > 0) {
0132 u32 real_mask = mask ? *mask : ~(u32)0;
0133 u32 new_value;
0134
0135 if (nbits < 32)
0136 real_mask &= ethnl_lower_bits(nbits);
0137 new_value = (*dst & ~real_mask) | (*value & real_mask);
0138 if (new_value != *dst) {
0139 *dst = new_value;
0140 *mod = true;
0141 }
0142
0143 if (nbits <= 32)
0144 break;
0145 dst++;
0146 nbits -= 32;
0147 value++;
0148 if (mask)
0149 mask++;
0150 }
0151 }
0152
0153 static bool ethnl_bitmap32_test_bit(const u32 *map, unsigned int index)
0154 {
0155 return map[index / 32] & (1U << (index % 32));
0156 }
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 int ethnl_bitset32_size(const u32 *val, const u32 *mask, unsigned int nbits,
0172 ethnl_string_array_t names, bool compact)
0173 {
0174 unsigned int len = 0;
0175
0176
0177 if (!mask)
0178 len += nla_total_size(sizeof(u32));
0179
0180 len += nla_total_size(sizeof(u32));
0181
0182 if (compact) {
0183 unsigned int nwords = DIV_ROUND_UP(nbits, 32);
0184
0185
0186 len += (mask ? 2 : 1) * nla_total_size(nwords * sizeof(u32));
0187 } else {
0188 unsigned int bits_len = 0;
0189 unsigned int bit_len, i;
0190
0191 for (i = 0; i < nbits; i++) {
0192 const char *name = names ? names[i] : NULL;
0193
0194 if (!ethnl_bitmap32_test_bit(mask ?: val, i))
0195 continue;
0196
0197 bit_len = nla_total_size(sizeof(u32));
0198
0199 if (name)
0200 bit_len += ethnl_strz_size(name);
0201
0202 if (mask && ethnl_bitmap32_test_bit(val, i))
0203 bit_len += nla_total_size(0);
0204
0205
0206 bits_len += nla_total_size(bit_len);
0207 }
0208
0209 len += nla_total_size(bits_len);
0210 }
0211
0212
0213 return nla_total_size(len);
0214 }
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 int ethnl_put_bitset32(struct sk_buff *skb, int attrtype, const u32 *val,
0233 const u32 *mask, unsigned int nbits,
0234 ethnl_string_array_t names, bool compact)
0235 {
0236 struct nlattr *nest;
0237 struct nlattr *attr;
0238
0239 nest = nla_nest_start(skb, attrtype);
0240 if (!nest)
0241 return -EMSGSIZE;
0242
0243 if (!mask && nla_put_flag(skb, ETHTOOL_A_BITSET_NOMASK))
0244 goto nla_put_failure;
0245 if (nla_put_u32(skb, ETHTOOL_A_BITSET_SIZE, nbits))
0246 goto nla_put_failure;
0247 if (compact) {
0248 unsigned int nwords = DIV_ROUND_UP(nbits, 32);
0249 unsigned int nbytes = nwords * sizeof(u32);
0250 u32 *dst;
0251
0252 attr = nla_reserve(skb, ETHTOOL_A_BITSET_VALUE, nbytes);
0253 if (!attr)
0254 goto nla_put_failure;
0255 dst = nla_data(attr);
0256 memcpy(dst, val, nbytes);
0257 if (nbits % 32)
0258 dst[nwords - 1] &= ethnl_lower_bits(nbits);
0259
0260 if (mask) {
0261 attr = nla_reserve(skb, ETHTOOL_A_BITSET_MASK, nbytes);
0262 if (!attr)
0263 goto nla_put_failure;
0264 dst = nla_data(attr);
0265 memcpy(dst, mask, nbytes);
0266 if (nbits % 32)
0267 dst[nwords - 1] &= ethnl_lower_bits(nbits);
0268 }
0269 } else {
0270 struct nlattr *bits;
0271 unsigned int i;
0272
0273 bits = nla_nest_start(skb, ETHTOOL_A_BITSET_BITS);
0274 if (!bits)
0275 goto nla_put_failure;
0276 for (i = 0; i < nbits; i++) {
0277 const char *name = names ? names[i] : NULL;
0278
0279 if (!ethnl_bitmap32_test_bit(mask ?: val, i))
0280 continue;
0281 attr = nla_nest_start(skb, ETHTOOL_A_BITSET_BITS_BIT);
0282 if (!attr)
0283 goto nla_put_failure;
0284 if (nla_put_u32(skb, ETHTOOL_A_BITSET_BIT_INDEX, i))
0285 goto nla_put_failure;
0286 if (name &&
0287 ethnl_put_strz(skb, ETHTOOL_A_BITSET_BIT_NAME, name))
0288 goto nla_put_failure;
0289 if (mask && ethnl_bitmap32_test_bit(val, i) &&
0290 nla_put_flag(skb, ETHTOOL_A_BITSET_BIT_VALUE))
0291 goto nla_put_failure;
0292 nla_nest_end(skb, attr);
0293 }
0294 nla_nest_end(skb, bits);
0295 }
0296
0297 nla_nest_end(skb, nest);
0298 return 0;
0299
0300 nla_put_failure:
0301 nla_nest_cancel(skb, nest);
0302 return -EMSGSIZE;
0303 }
0304
0305 static const struct nla_policy bitset_policy[] = {
0306 [ETHTOOL_A_BITSET_NOMASK] = { .type = NLA_FLAG },
0307 [ETHTOOL_A_BITSET_SIZE] = NLA_POLICY_MAX(NLA_U32,
0308 ETHNL_MAX_BITSET_SIZE),
0309 [ETHTOOL_A_BITSET_BITS] = { .type = NLA_NESTED },
0310 [ETHTOOL_A_BITSET_VALUE] = { .type = NLA_BINARY },
0311 [ETHTOOL_A_BITSET_MASK] = { .type = NLA_BINARY },
0312 };
0313
0314 static const struct nla_policy bit_policy[] = {
0315 [ETHTOOL_A_BITSET_BIT_INDEX] = { .type = NLA_U32 },
0316 [ETHTOOL_A_BITSET_BIT_NAME] = { .type = NLA_NUL_STRING },
0317 [ETHTOOL_A_BITSET_BIT_VALUE] = { .type = NLA_FLAG },
0318 };
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 int ethnl_bitset_is_compact(const struct nlattr *bitset, bool *compact)
0329 {
0330 struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
0331 int ret;
0332
0333 ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, bitset,
0334 bitset_policy, NULL);
0335 if (ret < 0)
0336 return ret;
0337
0338 if (tb[ETHTOOL_A_BITSET_BITS]) {
0339 if (tb[ETHTOOL_A_BITSET_VALUE] || tb[ETHTOOL_A_BITSET_MASK])
0340 return -EINVAL;
0341 *compact = false;
0342 return 0;
0343 }
0344 if (!tb[ETHTOOL_A_BITSET_SIZE] || !tb[ETHTOOL_A_BITSET_VALUE])
0345 return -EINVAL;
0346
0347 *compact = true;
0348 return 0;
0349 }
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 static int ethnl_name_to_idx(ethnl_string_array_t names, unsigned int n_names,
0360 const char *name)
0361 {
0362 unsigned int i;
0363
0364 if (!names)
0365 return -ENOENT;
0366
0367 for (i = 0; i < n_names; i++) {
0368
0369 if (!strncmp(names[i], name, ETH_GSTRING_LEN) &&
0370 strlen(name) <= ETH_GSTRING_LEN)
0371 return i;
0372 }
0373
0374 return -ENOENT;
0375 }
0376
0377 static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits,
0378 const struct nlattr *bit_attr, bool no_mask,
0379 ethnl_string_array_t names,
0380 struct netlink_ext_ack *extack)
0381 {
0382 struct nlattr *tb[ARRAY_SIZE(bit_policy)];
0383 int ret, idx;
0384
0385 ret = nla_parse_nested(tb, ARRAY_SIZE(bit_policy) - 1, bit_attr,
0386 bit_policy, extack);
0387 if (ret < 0)
0388 return ret;
0389
0390 if (tb[ETHTOOL_A_BITSET_BIT_INDEX]) {
0391 const char *name;
0392
0393 idx = nla_get_u32(tb[ETHTOOL_A_BITSET_BIT_INDEX]);
0394 if (idx >= nbits) {
0395 NL_SET_ERR_MSG_ATTR(extack,
0396 tb[ETHTOOL_A_BITSET_BIT_INDEX],
0397 "bit index too high");
0398 return -EOPNOTSUPP;
0399 }
0400 name = names ? names[idx] : NULL;
0401 if (tb[ETHTOOL_A_BITSET_BIT_NAME] && name &&
0402 strncmp(nla_data(tb[ETHTOOL_A_BITSET_BIT_NAME]), name,
0403 nla_len(tb[ETHTOOL_A_BITSET_BIT_NAME]))) {
0404 NL_SET_ERR_MSG_ATTR(extack, bit_attr,
0405 "bit index and name mismatch");
0406 return -EINVAL;
0407 }
0408 } else if (tb[ETHTOOL_A_BITSET_BIT_NAME]) {
0409 idx = ethnl_name_to_idx(names, nbits,
0410 nla_data(tb[ETHTOOL_A_BITSET_BIT_NAME]));
0411 if (idx < 0) {
0412 NL_SET_ERR_MSG_ATTR(extack,
0413 tb[ETHTOOL_A_BITSET_BIT_NAME],
0414 "bit name not found");
0415 return -EOPNOTSUPP;
0416 }
0417 } else {
0418 NL_SET_ERR_MSG_ATTR(extack, bit_attr,
0419 "neither bit index nor name specified");
0420 return -EINVAL;
0421 }
0422
0423 *index = idx;
0424 *val = no_mask || tb[ETHTOOL_A_BITSET_BIT_VALUE];
0425 return 0;
0426 }
0427
0428 static int
0429 ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
0430 const struct nlattr *attr, struct nlattr **tb,
0431 ethnl_string_array_t names,
0432 struct netlink_ext_ack *extack, bool *mod)
0433 {
0434 struct nlattr *bit_attr;
0435 bool no_mask;
0436 int rem;
0437 int ret;
0438
0439 if (tb[ETHTOOL_A_BITSET_VALUE]) {
0440 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE],
0441 "value only allowed in compact bitset");
0442 return -EINVAL;
0443 }
0444 if (tb[ETHTOOL_A_BITSET_MASK]) {
0445 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
0446 "mask only allowed in compact bitset");
0447 return -EINVAL;
0448 }
0449
0450 no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
0451 if (no_mask)
0452 ethnl_bitmap32_clear(bitmap, 0, nbits, mod);
0453
0454 nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
0455 bool old_val, new_val;
0456 unsigned int idx;
0457
0458 if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) {
0459 NL_SET_ERR_MSG_ATTR(extack, bit_attr,
0460 "only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS");
0461 return -EINVAL;
0462 }
0463 ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask,
0464 names, extack);
0465 if (ret < 0)
0466 return ret;
0467 old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32));
0468 if (new_val != old_val) {
0469 if (new_val)
0470 bitmap[idx / 32] |= ((u32)1 << (idx % 32));
0471 else
0472 bitmap[idx / 32] &= ~((u32)1 << (idx % 32));
0473 *mod = true;
0474 }
0475 }
0476
0477 return 0;
0478 }
0479
0480 static int ethnl_compact_sanity_checks(unsigned int nbits,
0481 const struct nlattr *nest,
0482 struct nlattr **tb,
0483 struct netlink_ext_ack *extack)
0484 {
0485 bool no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
0486 unsigned int attr_nbits, attr_nwords;
0487 const struct nlattr *test_attr;
0488
0489 if (no_mask && tb[ETHTOOL_A_BITSET_MASK]) {
0490 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
0491 "mask not allowed in list bitset");
0492 return -EINVAL;
0493 }
0494 if (!tb[ETHTOOL_A_BITSET_SIZE]) {
0495 NL_SET_ERR_MSG_ATTR(extack, nest,
0496 "missing size in compact bitset");
0497 return -EINVAL;
0498 }
0499 if (!tb[ETHTOOL_A_BITSET_VALUE]) {
0500 NL_SET_ERR_MSG_ATTR(extack, nest,
0501 "missing value in compact bitset");
0502 return -EINVAL;
0503 }
0504 if (!no_mask && !tb[ETHTOOL_A_BITSET_MASK]) {
0505 NL_SET_ERR_MSG_ATTR(extack, nest,
0506 "missing mask in compact nonlist bitset");
0507 return -EINVAL;
0508 }
0509
0510 attr_nbits = nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]);
0511 attr_nwords = DIV_ROUND_UP(attr_nbits, 32);
0512 if (nla_len(tb[ETHTOOL_A_BITSET_VALUE]) != attr_nwords * sizeof(u32)) {
0513 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE],
0514 "bitset value length does not match size");
0515 return -EINVAL;
0516 }
0517 if (tb[ETHTOOL_A_BITSET_MASK] &&
0518 nla_len(tb[ETHTOOL_A_BITSET_MASK]) != attr_nwords * sizeof(u32)) {
0519 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
0520 "bitset mask length does not match size");
0521 return -EINVAL;
0522 }
0523 if (attr_nbits <= nbits)
0524 return 0;
0525
0526 test_attr = no_mask ? tb[ETHTOOL_A_BITSET_VALUE] :
0527 tb[ETHTOOL_A_BITSET_MASK];
0528 if (ethnl_bitmap32_not_zero(nla_data(test_attr), nbits, attr_nbits)) {
0529 NL_SET_ERR_MSG_ATTR(extack, test_attr,
0530 "cannot modify bits past kernel bitset size");
0531 return -EINVAL;
0532 }
0533 return 0;
0534 }
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552 int ethnl_update_bitset32(u32 *bitmap, unsigned int nbits,
0553 const struct nlattr *attr, ethnl_string_array_t names,
0554 struct netlink_ext_ack *extack, bool *mod)
0555 {
0556 struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
0557 unsigned int change_bits;
0558 bool no_mask;
0559 int ret;
0560
0561 if (!attr)
0562 return 0;
0563 ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
0564 bitset_policy, extack);
0565 if (ret < 0)
0566 return ret;
0567
0568 if (tb[ETHTOOL_A_BITSET_BITS])
0569 return ethnl_update_bitset32_verbose(bitmap, nbits, attr, tb,
0570 names, extack, mod);
0571 ret = ethnl_compact_sanity_checks(nbits, attr, tb, extack);
0572 if (ret < 0)
0573 return ret;
0574
0575 no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
0576 change_bits = min_t(unsigned int,
0577 nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]), nbits);
0578 ethnl_bitmap32_update(bitmap, change_bits,
0579 nla_data(tb[ETHTOOL_A_BITSET_VALUE]),
0580 no_mask ? NULL :
0581 nla_data(tb[ETHTOOL_A_BITSET_MASK]),
0582 mod);
0583 if (no_mask && change_bits < nbits)
0584 ethnl_bitmap32_clear(bitmap, change_bits, nbits, mod);
0585
0586 return 0;
0587 }
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604 int ethnl_parse_bitset(unsigned long *val, unsigned long *mask,
0605 unsigned int nbits, const struct nlattr *attr,
0606 ethnl_string_array_t names,
0607 struct netlink_ext_ack *extack)
0608 {
0609 struct nlattr *tb[ARRAY_SIZE(bitset_policy)];
0610 const struct nlattr *bit_attr;
0611 bool no_mask;
0612 int rem;
0613 int ret;
0614
0615 if (!attr)
0616 return 0;
0617 ret = nla_parse_nested(tb, ARRAY_SIZE(bitset_policy) - 1, attr,
0618 bitset_policy, extack);
0619 if (ret < 0)
0620 return ret;
0621 no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
0622
0623 if (!tb[ETHTOOL_A_BITSET_BITS]) {
0624 unsigned int change_bits;
0625
0626 ret = ethnl_compact_sanity_checks(nbits, attr, tb, extack);
0627 if (ret < 0)
0628 return ret;
0629
0630 change_bits = nla_get_u32(tb[ETHTOOL_A_BITSET_SIZE]);
0631 if (change_bits > nbits)
0632 change_bits = nbits;
0633 bitmap_from_arr32(val, nla_data(tb[ETHTOOL_A_BITSET_VALUE]),
0634 change_bits);
0635 if (change_bits < nbits)
0636 bitmap_clear(val, change_bits, nbits - change_bits);
0637 if (no_mask) {
0638 bitmap_fill(mask, nbits);
0639 } else {
0640 bitmap_from_arr32(mask,
0641 nla_data(tb[ETHTOOL_A_BITSET_MASK]),
0642 change_bits);
0643 if (change_bits < nbits)
0644 bitmap_clear(mask, change_bits,
0645 nbits - change_bits);
0646 }
0647
0648 return 0;
0649 }
0650
0651 if (tb[ETHTOOL_A_BITSET_VALUE]) {
0652 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_VALUE],
0653 "value only allowed in compact bitset");
0654 return -EINVAL;
0655 }
0656 if (tb[ETHTOOL_A_BITSET_MASK]) {
0657 NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_BITSET_MASK],
0658 "mask only allowed in compact bitset");
0659 return -EINVAL;
0660 }
0661
0662 bitmap_zero(val, nbits);
0663 if (no_mask)
0664 bitmap_fill(mask, nbits);
0665 else
0666 bitmap_zero(mask, nbits);
0667
0668 nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
0669 unsigned int idx;
0670 bool bit_val;
0671
0672 ret = ethnl_parse_bit(&idx, &bit_val, nbits, bit_attr, no_mask,
0673 names, extack);
0674 if (ret < 0)
0675 return ret;
0676 if (bit_val)
0677 __set_bit(idx, val);
0678 if (!no_mask)
0679 __set_bit(idx, mask);
0680 }
0681
0682 return 0;
0683 }
0684
0685 #if BITS_PER_LONG == 64 && defined(__BIG_ENDIAN)
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696 #define ETHNL_SMALL_BITMAP_BITS 128
0697 #define ETHNL_SMALL_BITMAP_WORDS DIV_ROUND_UP(ETHNL_SMALL_BITMAP_BITS, 32)
0698
0699 int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask,
0700 unsigned int nbits, ethnl_string_array_t names,
0701 bool compact)
0702 {
0703 u32 small_mask32[ETHNL_SMALL_BITMAP_WORDS];
0704 u32 small_val32[ETHNL_SMALL_BITMAP_WORDS];
0705 u32 *mask32;
0706 u32 *val32;
0707 int ret;
0708
0709 if (nbits > ETHNL_SMALL_BITMAP_BITS) {
0710 unsigned int nwords = DIV_ROUND_UP(nbits, 32);
0711
0712 val32 = kmalloc_array(2 * nwords, sizeof(u32), GFP_KERNEL);
0713 if (!val32)
0714 return -ENOMEM;
0715 mask32 = val32 + nwords;
0716 } else {
0717 val32 = small_val32;
0718 mask32 = small_mask32;
0719 }
0720
0721 bitmap_to_arr32(val32, val, nbits);
0722 if (mask)
0723 bitmap_to_arr32(mask32, mask, nbits);
0724 else
0725 mask32 = NULL;
0726 ret = ethnl_bitset32_size(val32, mask32, nbits, names, compact);
0727
0728 if (nbits > ETHNL_SMALL_BITMAP_BITS)
0729 kfree(val32);
0730
0731 return ret;
0732 }
0733
0734 int ethnl_put_bitset(struct sk_buff *skb, int attrtype,
0735 const unsigned long *val, const unsigned long *mask,
0736 unsigned int nbits, ethnl_string_array_t names,
0737 bool compact)
0738 {
0739 u32 small_mask32[ETHNL_SMALL_BITMAP_WORDS];
0740 u32 small_val32[ETHNL_SMALL_BITMAP_WORDS];
0741 u32 *mask32;
0742 u32 *val32;
0743 int ret;
0744
0745 if (nbits > ETHNL_SMALL_BITMAP_BITS) {
0746 unsigned int nwords = DIV_ROUND_UP(nbits, 32);
0747
0748 val32 = kmalloc_array(2 * nwords, sizeof(u32), GFP_KERNEL);
0749 if (!val32)
0750 return -ENOMEM;
0751 mask32 = val32 + nwords;
0752 } else {
0753 val32 = small_val32;
0754 mask32 = small_mask32;
0755 }
0756
0757 bitmap_to_arr32(val32, val, nbits);
0758 if (mask)
0759 bitmap_to_arr32(mask32, mask, nbits);
0760 else
0761 mask32 = NULL;
0762 ret = ethnl_put_bitset32(skb, attrtype, val32, mask32, nbits, names,
0763 compact);
0764
0765 if (nbits > ETHNL_SMALL_BITMAP_BITS)
0766 kfree(val32);
0767
0768 return ret;
0769 }
0770
0771 int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits,
0772 const struct nlattr *attr, ethnl_string_array_t names,
0773 struct netlink_ext_ack *extack, bool *mod)
0774 {
0775 u32 small_bitmap32[ETHNL_SMALL_BITMAP_WORDS];
0776 u32 *bitmap32 = small_bitmap32;
0777 bool u32_mod = false;
0778 int ret;
0779
0780 if (nbits > ETHNL_SMALL_BITMAP_BITS) {
0781 unsigned int dst_words = DIV_ROUND_UP(nbits, 32);
0782
0783 bitmap32 = kmalloc_array(dst_words, sizeof(u32), GFP_KERNEL);
0784 if (!bitmap32)
0785 return -ENOMEM;
0786 }
0787
0788 bitmap_to_arr32(bitmap32, bitmap, nbits);
0789 ret = ethnl_update_bitset32(bitmap32, nbits, attr, names, extack,
0790 &u32_mod);
0791 if (u32_mod) {
0792 bitmap_from_arr32(bitmap, bitmap32, nbits);
0793 *mod = true;
0794 }
0795
0796 if (nbits > ETHNL_SMALL_BITMAP_BITS)
0797 kfree(bitmap32);
0798
0799 return ret;
0800 }
0801
0802 #else
0803
0804
0805
0806
0807
0808 int ethnl_bitset_size(const unsigned long *val, const unsigned long *mask,
0809 unsigned int nbits, ethnl_string_array_t names,
0810 bool compact)
0811 {
0812 return ethnl_bitset32_size((const u32 *)val, (const u32 *)mask, nbits,
0813 names, compact);
0814 }
0815
0816 int ethnl_put_bitset(struct sk_buff *skb, int attrtype,
0817 const unsigned long *val, const unsigned long *mask,
0818 unsigned int nbits, ethnl_string_array_t names,
0819 bool compact)
0820 {
0821 return ethnl_put_bitset32(skb, attrtype, (const u32 *)val,
0822 (const u32 *)mask, nbits, names, compact);
0823 }
0824
0825 int ethnl_update_bitset(unsigned long *bitmap, unsigned int nbits,
0826 const struct nlattr *attr, ethnl_string_array_t names,
0827 struct netlink_ext_ack *extack, bool *mod)
0828 {
0829 return ethnl_update_bitset32((u32 *)bitmap, nbits, attr, names, extack,
0830 mod);
0831 }
0832
0833 #endif