.. | .. |
---|
716 | 716 | struct nlattr *est, bool ovr, |
---|
717 | 717 | struct netlink_ext_ack *extack) |
---|
718 | 718 | { |
---|
719 | | - int err; |
---|
| 719 | + int err, ifindex = -1; |
---|
720 | 720 | |
---|
721 | 721 | err = tcf_exts_validate(net, tp, tb, est, &n->exts, ovr, true, extack); |
---|
722 | 722 | if (err < 0) |
---|
723 | 723 | return err; |
---|
| 724 | + |
---|
| 725 | + if (tb[TCA_U32_INDEV]) { |
---|
| 726 | + ifindex = tcf_change_indev(net, tb[TCA_U32_INDEV], extack); |
---|
| 727 | + if (ifindex < 0) |
---|
| 728 | + return -EINVAL; |
---|
| 729 | + } |
---|
724 | 730 | |
---|
725 | 731 | if (tb[TCA_U32_LINK]) { |
---|
726 | 732 | u32 handle = nla_get_u32(tb[TCA_U32_LINK]); |
---|
.. | .. |
---|
756 | 762 | tcf_bind_filter(tp, &n->res, base); |
---|
757 | 763 | } |
---|
758 | 764 | |
---|
759 | | - if (tb[TCA_U32_INDEV]) { |
---|
760 | | - int ret; |
---|
761 | | - ret = tcf_change_indev(net, tb[TCA_U32_INDEV], extack); |
---|
762 | | - if (ret < 0) |
---|
763 | | - return -EINVAL; |
---|
764 | | - n->ifindex = ret; |
---|
765 | | - } |
---|
| 765 | + if (ifindex >= 0) |
---|
| 766 | + n->ifindex = ifindex; |
---|
| 767 | + |
---|
766 | 768 | return 0; |
---|
767 | 769 | } |
---|
768 | 770 | |
---|
.. | .. |
---|
810 | 812 | |
---|
811 | 813 | new->ifindex = n->ifindex; |
---|
812 | 814 | new->fshift = n->fshift; |
---|
813 | | - new->res = n->res; |
---|
814 | 815 | new->flags = n->flags; |
---|
815 | 816 | RCU_INIT_POINTER(new->ht_down, ht); |
---|
816 | 817 | |
---|
.. | .. |
---|
997 | 998 | return -EINVAL; |
---|
998 | 999 | } |
---|
999 | 1000 | |
---|
| 1001 | + /* At this point, we need to derive the new handle that will be used to |
---|
| 1002 | + * uniquely map the identity of this table match entry. The |
---|
| 1003 | + * identity of the entry that we need to construct is 32 bits made of: |
---|
| 1004 | + * htid(12b):bucketid(8b):node/entryid(12b) |
---|
| 1005 | + * |
---|
| 1006 | + * At this point _we have the table(ht)_ in which we will insert this |
---|
| 1007 | + * entry. We carry the table's id in variable "htid". |
---|
| 1008 | + * Note that earlier code picked the ht selection either by a) the user |
---|
| 1009 | + * providing the htid specified via TCA_U32_HASH attribute or b) when |
---|
| 1010 | + * no such attribute is passed then the root ht, is default to at ID |
---|
| 1011 | + * 0x[800][00][000]. Rule: the root table has a single bucket with ID 0. |
---|
| 1012 | + * If OTOH the user passed us the htid, they may also pass a bucketid of |
---|
| 1013 | + * choice. 0 is fine. For example a user htid is 0x[600][01][000] it is |
---|
| 1014 | + * indicating hash bucketid of 1. Rule: the entry/node ID _cannot_ be |
---|
| 1015 | + * passed via the htid, so even if it was non-zero it will be ignored. |
---|
| 1016 | + * |
---|
| 1017 | + * We may also have a handle, if the user passed one. The handle also |
---|
| 1018 | + * carries the same addressing of htid(12b):bucketid(8b):node/entryid(12b). |
---|
| 1019 | + * Rule: the bucketid on the handle is ignored even if one was passed; |
---|
| 1020 | + * rather the value on "htid" is always assumed to be the bucketid. |
---|
| 1021 | + */ |
---|
1000 | 1022 | if (handle) { |
---|
| 1023 | + /* Rule: The htid from handle and tableid from htid must match */ |
---|
1001 | 1024 | if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) { |
---|
1002 | 1025 | NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch"); |
---|
1003 | 1026 | return -EINVAL; |
---|
1004 | 1027 | } |
---|
1005 | | - handle = htid | TC_U32_NODE(handle); |
---|
1006 | | - err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle, |
---|
1007 | | - GFP_KERNEL); |
---|
1008 | | - if (err) |
---|
1009 | | - return err; |
---|
1010 | | - } else |
---|
| 1028 | + /* Ok, so far we have a valid htid(12b):bucketid(8b) but we |
---|
| 1029 | + * need to finalize the table entry identification with the last |
---|
| 1030 | + * part - the node/entryid(12b)). Rule: Nodeid _cannot be 0_ for |
---|
| 1031 | + * entries. Rule: nodeid of 0 is reserved only for tables(see |
---|
| 1032 | + * earlier code which processes TC_U32_DIVISOR attribute). |
---|
| 1033 | + * Rule: The nodeid can only be derived from the handle (and not |
---|
| 1034 | + * htid). |
---|
| 1035 | + * Rule: if the handle specified zero for the node id example |
---|
| 1036 | + * 0x60000000, then pick a new nodeid from the pool of IDs |
---|
| 1037 | + * this hash table has been allocating from. |
---|
| 1038 | + * If OTOH it is specified (i.e for example the user passed a |
---|
| 1039 | + * handle such as 0x60000123), then we use it generate our final |
---|
| 1040 | + * handle which is used to uniquely identify the match entry. |
---|
| 1041 | + */ |
---|
| 1042 | + if (!TC_U32_NODE(handle)) { |
---|
| 1043 | + handle = gen_new_kid(ht, htid); |
---|
| 1044 | + } else { |
---|
| 1045 | + handle = htid | TC_U32_NODE(handle); |
---|
| 1046 | + err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, |
---|
| 1047 | + handle, GFP_KERNEL); |
---|
| 1048 | + if (err) |
---|
| 1049 | + return err; |
---|
| 1050 | + } |
---|
| 1051 | + } else { |
---|
| 1052 | + /* The user did not give us a handle; lets just generate one |
---|
| 1053 | + * from the table's pool of nodeids. |
---|
| 1054 | + */ |
---|
1011 | 1055 | handle = gen_new_kid(ht, htid); |
---|
| 1056 | + } |
---|
1012 | 1057 | |
---|
1013 | 1058 | if (tb[TCA_U32_SEL] == NULL) { |
---|
1014 | 1059 | NL_SET_ERR_MSG_MOD(extack, "Selector not specified"); |
---|