@@ -280,6 +280,10 @@ struct nfct_filter {
uint32_t mask;
} mark[__FILTER_MARK_MAX];
+ uint32_t zone_elems;
+#define __FILTER_ZONE_MAX 127
+ uint16_t zone[__FILTER_ZONE_MAX];
+
uint32_t set[1];
};
@@ -510,6 +510,7 @@ enum nfct_filter_attr {
NFCT_FILTER_SRC_IPV6, /* struct nfct_filter_ipv6 */
NFCT_FILTER_DST_IPV6, /* struct nfct_filter_ipv6 */
NFCT_FILTER_MARK, /* struct nfct_filter_dump_mark */
+ NFCT_FILTER_ZONE, /* uint16_t */
NFCT_FILTER_MAX
};
new file mode 100644
GIT binary patch
literal 6148
zcmeHKJ8Hu~5S?*U$hdKta<7mZEJi+oFW`_siUbKvl3JC|<)it{2V)_n38V>c#LU|r
z&0C>YXfz_CyRX+Lk*$cda6>s;n48@<pV=xi3WVc~PdUl6yvY0aVOG7IFzy<RL3&(w
z{8Rri^lx$UGL=~>Kn17(6`%rC;1>#5?}fFSKt?J+1*pJH0sB4_xM58k1O3y1;3ELA
zLD~&#pCy3B62O``1|kE~paO%cIbvwgkuO<S6UV@yi{|j5`DD!rMg8eGzj(Q54P>MO
zRA8#WLu|L!|M&18=Km>)J1Rg0{*?mSbcb$-SIXWxdpYa11%8BE%>{0TwNnth9Rs}`
hV`J_3(Tk$4*c$h1;uz?3<ed)W&w%MdqXK`ez!e2N6_Nk|
literal 0
HcmV?d00001
@@ -738,6 +738,58 @@ bsf_add_mark_filter(const struct nfct_filter *f, struct sock_filter *this)
return j;
}
+static int
+bsf_add_zone_filter(const struct nfct_filter *f, struct sock_filter *this)
+{
+ unsigned int i, j;
+ unsigned int jt;
+ struct stack *s;
+ struct jump jmp;
+ struct sock_filter __code = {
+ /* if (A == 0) skip next two */
+ .code = BPF_JMP|BPF_JEQ|BPF_K,
+ .k = 0,
+ .jt = 2,
+ .jf = 0,
+ };
+
+ /* nothing to filter, skip */
+ if (f->zone_elems == 0)
+ return 0;
+
+ /* 127 max filterable zones. One JMP instruction per zone. */
+ s = stack_create(sizeof(struct jump), 127);
+ if (s == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ jt = 1;
+ j = 0;
+ j += nfct_bsf_load_payload_offset(this, j); /* A = nla header offset */
+ j += nfct_bsf_find_attr(this, CTA_ZONE, j); /* A = CTA_ZONE offset, started from A */
+ memcpy(&this[j], &__code, sizeof(__code)); /* if A == 0 skip next two op */
+ j += NEW_POS(__code);
+ j += nfct_bsf_x_equal_a(this, j); /* X = A <CTA_ZONE offset> */
+ j += nfct_bsf_load_attr(this, BPF_H, j); /* A = skb->data[X:X + BPF_H] */
+
+ for (i = 0; i < f->zone_elems; i++) {
+ j += nfct_bsf_cmp_k_stack(this, f->zone[i], jt - j, j, s);
+ }
+
+ while (stack_pop(s, &jmp) != -1)
+ this[jmp.line].jt += jmp.jt + j;
+
+ if (f->logic[NFCT_FILTER_ZONE] == NFCT_FILTER_LOGIC_NEGATIVE)
+ j += nfct_bsf_jump_to(this, 1, j);
+
+ j += nfct_bsf_ret_verdict(this, NFCT_FILTER_REJECT, j);
+
+ stack_destroy(s);
+
+ return j;
+}
+
/* this buffer must be big enough to store all the autogenerated lines */
#define BSF_BUFFER_SIZE 2048
@@ -774,6 +826,9 @@ int __setup_netlink_socket_filter(int fd, struct nfct_filter *f)
j += bsf_add_mark_filter(f, &bsf[j]);
show_filter(bsf, from, j, "---- check mark ----");
from = j;
+ j += bsf_add_zone_filter(f, &bsf[j]);
+ show_filter(bsf, from, j, "---- check zone ----");
+ from = j;
/* nothing to filter, skip */
if (j == 0)
@@ -104,6 +104,15 @@ static void filter_attr_mark(struct nfct_filter *filter, const void *value)
filter->mark_elems++;
}
+static void filter_attr_zone(struct nfct_filter *filter, const void *value)
+{
+ if (filter->zone_elems >= __FILTER_ZONE_MAX)
+ return;
+
+ filter->zone[filter->zone_elems] = *(uint16_t *) value;
+ filter->zone_elems++;
+}
+
const filter_attr filter_attr_array[NFCT_FILTER_MAX] = {
[NFCT_FILTER_L4PROTO] = filter_attr_l4proto,
[NFCT_FILTER_L4PROTO_STATE] = filter_attr_l4proto_state,
@@ -112,4 +121,5 @@ const filter_attr filter_attr_array[NFCT_FILTER_MAX] = {
[NFCT_FILTER_SRC_IPV6] = filter_attr_src_ipv6,
[NFCT_FILTER_DST_IPV6] = filter_attr_dst_ipv6,
[NFCT_FILTER_MARK] = filter_attr_mark,
+ [NFCT_FILTER_ZONE] = filter_attr_zone,
};
This patch adds support for filtering CT entries by their zones using bsf. Max number of zones for filtering is 127. (Although it can be supported till 255 but keeping it consistent with IPv4 and mark filtering). Entries which does not ct-zone set will be treated as ct-zone=0. Signed-off-by: Priyankar Jain <priyankar.jain@nutanix.com> --- include/internal/object.h | 4 ++ .../libnetfilter_conntrack.h | 1 + src/.DS_Store | Bin 0 -> 6148 bytes src/conntrack/bsf.c | 55 ++++++++++++++++++ src/conntrack/filter.c | 10 ++++ 5 files changed, 70 insertions(+) create mode 100644 src/.DS_Store