* New multiple DSCP match by "-m dscp --dscp-multi value,value,..."
@ 2015-08-03 4:04 Kyeong Yoo
2015-08-04 9:19 ` Pablo Neira Ayuso
0 siblings, 1 reply; 4+ messages in thread
From: Kyeong Yoo @ 2015-08-03 4:04 UTC (permalink / raw)
To: netfilter-devel@vger.kernel.org
[-- Attachment #1: Type: text/plain, Size: 903 bytes --]
I found this is useful for me to match multiple DSCP values in a rule.
For example, if you want to handle traffic with a list of DSCP same way,
instead of using this:
-A FORWARD ...cond1... -m dscp --dscp-class AF11 -j TARGET
-A FORWARD ...cond1... -m dscp --dscp-class AF21 -j TARGET
-A FORWARD ...cond1... -m dscp --dscp-class AF31 -j TARGET
-A FORWARD ...cond2... -m dscp --dscp 10 -j TARGET
-A FORWARD ...cond2... -m dscp --dscp 20 -j TARGET
you can use:
-A FORWARD ...cond1... -m dscp --dscp-multi AF11,AF21,AF31 -j TARGET
-A FORWARD ...cond2... -m dscp --dscp-multi 10,20 -j TARGET
This is mainly convenient if you want to have 1-to-1 mapping from your
app to iptables rule.
Also you don't need to add up packet counts (for example) from multiple
rules.
Does anyone have an idea whether this will be useful for others and
worth to push?
Thanks.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: linux-dscp-multi.patch --]
[-- Type: text/x-patch; name="linux-dscp-multi.patch", Size: 2191 bytes --]
commit 97958cdb209a6babc88fdeb10893597dcb8856d5
Author: Kyeong Yoo <kyeong.yoo@alliedtelesis.co.nz>
Date: Mon Jul 27 23:46:05 2015 +1200
[NETFILTER]: support multiple DSCP value match by "-m dscp --dscp-multi"
Current "dscp" match supports one DSCP value in a rule.
This patch enhances "dscp" match with multiple values:
-m dscp --dscp-multi value,value,...
As there are 64 values possible in DSCP field (6 bits), list of values
are stored in a 64-bit bitmap.
Reviewed-by: Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>
Reviewed-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
diff --git a/include/uapi/linux/netfilter/xt_dscp.h b/include/uapi/linux/netfilter/xt_dscp.h
index 15f8932..bea99fa 100644
--- a/include/uapi/linux/netfilter/xt_dscp.h
+++ b/include/uapi/linux/netfilter/xt_dscp.h
@@ -16,10 +16,17 @@
#define XT_DSCP_SHIFT 2
#define XT_DSCP_MAX 0x3f /* 00111111 */
+#define dscp_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1U << (idx & 31))
+#define dscp_test_bit(bmap, idx) \
+ (((1U << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
/* match info */
struct xt_dscp_info {
__u8 dscp;
__u8 invert;
+ __u8 multi;
+ __u32 dscp_bitmap[(XT_DSCP_MAX >> 5) + 1];
};
struct xt_tos_match_info {
diff --git a/net/netfilter/xt_dscp.c b/net/netfilter/xt_dscp.c
index 64670fc..f127f04 100644
--- a/net/netfilter/xt_dscp.c
+++ b/net/netfilter/xt_dscp.c
@@ -30,6 +30,8 @@ dscp_mt(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_dscp_info *info = par->matchinfo;
u_int8_t dscp = ipv4_get_dsfield(ip_hdr(skb)) >> XT_DSCP_SHIFT;
+ if (info->multi)
+ return (dscp_test_bit(info->dscp_bitmap, dscp) != 0) ^ !!info->invert;
return (dscp == info->dscp) ^ !!info->invert;
}
@@ -39,6 +41,8 @@ dscp_mt6(const struct sk_buff *skb, struct xt_action_param *par)
const struct xt_dscp_info *info = par->matchinfo;
u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(skb)) >> XT_DSCP_SHIFT;
+ if (info->multi)
+ return (dscp_test_bit(info->dscp_bitmap, dscp) != 0) ^ !!info->invert;
return (dscp == info->dscp) ^ !!info->invert;
}
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: iptables-dscp-multi.patch --]
[-- Type: text/x-patch; name="iptables-dscp-multi.patch", Size: 5893 bytes --]
commit a6370996fd612a538474209195c3fbdd7dfeef76
Author: Kyeong Yoo <kyeong.yoo@alliedtelesis.co.nz>
Date: Wed Jul 29 09:38:51 2015 +1200
extensions: libxt_dscp: allow multiple DSCP value match (--dscp-multi)
Current "dscp" match supports one DSCP value in a rule.
This patch enhances "dscp" match with multiple values ("--dscp-multi" option):
-m dscp --dscp-multi value,value,...
DSCP value should be between 0 and 63 or valid DSCP name like AF11, etc.
Reviewed-by: Luuk Paulussen <luuk.paulussen@alliedtelesis.co.nz>
Reviewed-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
diff --git a/extensions/libxt_dscp.c b/extensions/libxt_dscp.c
index 02b22a4..ebf8723 100644
--- a/extensions/libxt_dscp.c
+++ b/extensions/libxt_dscp.c
@@ -14,6 +14,7 @@
*/
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <xtables.h>
#include <linux/netfilter/xt_dscp.h>
@@ -23,8 +24,10 @@
enum {
O_DSCP = 0,
O_DSCP_CLASS,
+ O_DSCP_MULTI,
F_DSCP = 1 << O_DSCP,
F_DSCP_CLASS = 1 << O_DSCP_CLASS,
+ F_DSCP_MULTI = 1 << O_DSCP_MULTI,
};
static void dscp_help(void)
@@ -36,20 +39,78 @@ static void dscp_help(void)
" or in hex (ex: 0x20)\n"
"[!] --dscp-class name Match the DiffServ class. This value may\n"
" be any of the BE,EF, AFxx or CSx classes\n"
+"[!] --dscp-multi value[,value] Match DSCP value(s) in decimal or in hex\n"
"\n"
-" These two options are mutually exclusive !\n");
+" These three options are mutually exclusive !\n");
}
static const struct xt_option_entry dscp_opts[] = {
- {.name = "dscp", .id = O_DSCP, .excl = F_DSCP_CLASS,
+ {.name = "dscp", .id = O_DSCP, .excl = F_DSCP_CLASS | F_DSCP_MULTI,
.type = XTTYPE_UINT8, .min = 0, .max = XT_DSCP_MAX,
.flags = XTOPT_INVERT | XTOPT_PUT,
XTOPT_POINTER(struct xt_dscp_info, dscp)},
- {.name = "dscp-class", .id = O_DSCP_CLASS, .excl = F_DSCP,
+ {.name = "dscp-class", .id = O_DSCP_CLASS, .excl = F_DSCP | F_DSCP_MULTI,
+ .type = XTTYPE_STRING, .flags = XTOPT_INVERT},
+ {.name = "dscp-multi", .id = O_DSCP_MULTI, .excl = F_DSCP | F_DSCP_CLASS,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT},
XTOPT_TABLEEND,
};
+static void dscp_multi_parse(struct xt_dscp_info *dinfo, const char *arg)
+{
+ char *buffer, *str, *next;
+ unsigned int dscp;
+
+ buffer = strdup(arg);
+ if (!buffer) xtables_error(OTHER_PROBLEM, "strdup failed");
+
+ for (str = buffer; str; str = next)
+ {
+ if ((next = strchr(str, ',')) != NULL)
+ *next++ = '\0';
+ /* Try to convert as a number first and then as a DSCP name.
+ * Note class_to_dscp() calls exit() on error after printing error message. */
+ if (!xtables_strtoui(str, NULL, &dscp, 0, XT_DSCP_MAX))
+ dscp = class_to_dscp(str);
+ dscp_set_bit(dinfo->dscp_bitmap, dscp);
+ }
+ free(buffer);
+}
+
+static void dscp_multi_print(const struct xt_dscp_info *dinfo)
+{
+ unsigned char dscp;
+ int count = 0;
+
+ for (dscp = 0; dscp <= XT_DSCP_MAX; dscp++)
+ {
+ if (dscp_test_bit(dinfo->dscp_bitmap, dscp)) {
+ if (count == 0)
+ printf(" DSCP multi-match %s0x%02x", dinfo->invert ? "!" : "", dscp);
+ else
+ printf(",0x%02x", dscp);
+ count++;
+ }
+ }
+}
+
+static void dscp_multi_save(const struct xt_dscp_info *dinfo)
+{
+ unsigned char dscp;
+ int count = 0;
+
+ for (dscp = 0; dscp <= XT_DSCP_MAX; dscp++)
+ {
+ if (dscp_test_bit(dinfo->dscp_bitmap, dscp)) {
+ if (count == 0)
+ printf("%s --dscp-multi 0x%02x", dinfo->invert ? " !" : "", dscp);
+ else
+ printf(",0x%02x", dscp);
+ count++;
+ }
+ }
+}
+
static void dscp_parse(struct xt_option_call *cb)
{
struct xt_dscp_info *dinfo = cb->data;
@@ -65,6 +126,12 @@ static void dscp_parse(struct xt_option_call *cb)
if (cb->invert)
dinfo->invert = 1;
break;
+ case O_DSCP_MULTI:
+ dinfo->multi = 1;
+ dscp_multi_parse(dinfo, cb->arg);
+ if (cb->invert)
+ dinfo->invert = 1;
+ break;
}
}
@@ -72,7 +139,7 @@ static void dscp_check(struct xt_fcheck_call *cb)
{
if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
- "DSCP match: Parameter --dscp is required");
+ "DSCP match: Parameter --dscp or --dscp-multi is required");
}
static void
@@ -80,7 +147,10 @@ dscp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_dscp_info *dinfo =
(const struct xt_dscp_info *)match->data;
- printf(" DSCP match %s0x%02x", dinfo->invert ? "!" : "", dinfo->dscp);
+ if (dinfo->multi)
+ dscp_multi_print(dinfo);
+ else
+ printf(" DSCP match %s0x%02x", dinfo->invert ? "!" : "", dinfo->dscp);
}
static void dscp_save(const void *ip, const struct xt_entry_match *match)
@@ -88,7 +158,10 @@ static void dscp_save(const void *ip, const struct xt_entry_match *match)
const struct xt_dscp_info *dinfo =
(const struct xt_dscp_info *)match->data;
- printf("%s --dscp 0x%02x", dinfo->invert ? " !" : "", dinfo->dscp);
+ if (dinfo->multi)
+ dscp_multi_save(dinfo);
+ else
+ printf("%s --dscp 0x%02x", dinfo->invert ? " !" : "", dinfo->dscp);
}
static struct xtables_match dscp_match = {
diff --git a/include/linux/netfilter/xt_dscp.h b/include/linux/netfilter/xt_dscp.h
index 15f8932..bea99fa 100644
--- a/include/linux/netfilter/xt_dscp.h
+++ b/include/linux/netfilter/xt_dscp.h
@@ -16,10 +16,17 @@
#define XT_DSCP_SHIFT 2
#define XT_DSCP_MAX 0x3f /* 00111111 */
+#define dscp_set_bit(bmap, idx) \
+ (bmap[(idx) >> 5] |= 1U << (idx & 31))
+#define dscp_test_bit(bmap, idx) \
+ (((1U << (idx & 31)) & bmap[(idx) >> 5]) != 0)
+
/* match info */
struct xt_dscp_info {
__u8 dscp;
__u8 invert;
+ __u8 multi;
+ __u32 dscp_bitmap[(XT_DSCP_MAX >> 5) + 1];
};
struct xt_tos_match_info {
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: New multiple DSCP match by "-m dscp --dscp-multi value,value,..."
2015-08-03 4:04 New multiple DSCP match by "-m dscp --dscp-multi value,value,..." Kyeong Yoo
@ 2015-08-04 9:19 ` Pablo Neira Ayuso
2015-08-04 9:25 ` Florian Westphal
0 siblings, 1 reply; 4+ messages in thread
From: Pablo Neira Ayuso @ 2015-08-04 9:19 UTC (permalink / raw)
To: Kyeong Yoo; +Cc: netfilter-devel@vger.kernel.org
On Mon, Aug 03, 2015 at 04:04:46AM +0000, Kyeong Yoo wrote:
> I found this is useful for me to match multiple DSCP values in a rule.
>
> For example, if you want to handle traffic with a list of DSCP same way,
> instead of using this:
>
> -A FORWARD ...cond1... -m dscp --dscp-class AF11 -j TARGET
> -A FORWARD ...cond1... -m dscp --dscp-class AF21 -j TARGET
> -A FORWARD ...cond1... -m dscp --dscp-class AF31 -j TARGET
> -A FORWARD ...cond2... -m dscp --dscp 10 -j TARGET
> -A FORWARD ...cond2... -m dscp --dscp 20 -j TARGET
>
> you can use:
>
> -A FORWARD ...cond1... -m dscp --dscp-multi AF11,AF21,AF31 -j TARGET
> -A FORWARD ...cond2... -m dscp --dscp-multi 10,20 -j TARGET
We support multiple matches in a rule for long time already:
-A FORWARD ...cond1... -m dscp --dscp-class AF11 \
-m dscp --dscp-class AF21 \
-m dscp --dscp-class AF31 \
-j TARGET
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: New multiple DSCP match by "-m dscp --dscp-multi value,value,..."
2015-08-04 9:19 ` Pablo Neira Ayuso
@ 2015-08-04 9:25 ` Florian Westphal
2015-08-04 9:35 ` Pablo Neira Ayuso
0 siblings, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2015-08-04 9:25 UTC (permalink / raw)
To: Pablo Neira Ayuso; +Cc: Kyeong Yoo, netfilter-devel@vger.kernel.org
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Mon, Aug 03, 2015 at 04:04:46AM +0000, Kyeong Yoo wrote:
> > I found this is useful for me to match multiple DSCP values in a rule.
> >
> > For example, if you want to handle traffic with a list of DSCP same way,
> > instead of using this:
> >
> > -A FORWARD ...cond1... -m dscp --dscp-class AF11 -j TARGET
> > -A FORWARD ...cond1... -m dscp --dscp-class AF21 -j TARGET
> > -A FORWARD ...cond1... -m dscp --dscp-class AF31 -j TARGET
> > -A FORWARD ...cond2... -m dscp --dscp 10 -j TARGET
> > -A FORWARD ...cond2... -m dscp --dscp 20 -j TARGET
> >
> > you can use:
> >
> > -A FORWARD ...cond1... -m dscp --dscp-multi AF11,AF21,AF31 -j TARGET
> > -A FORWARD ...cond2... -m dscp --dscp-multi 10,20 -j TARGET
>
> We support multiple matches in a rule for long time already:
>
> -A FORWARD ...cond1... -m dscp --dscp-class AF11 \
> -m dscp --dscp-class AF21 \
> -m dscp --dscp-class AF31 \
Yes, but that won't work since this is foo && bar, not foo || bar.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: New multiple DSCP match by "-m dscp --dscp-multi value,value,..."
2015-08-04 9:25 ` Florian Westphal
@ 2015-08-04 9:35 ` Pablo Neira Ayuso
0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2015-08-04 9:35 UTC (permalink / raw)
To: Florian Westphal; +Cc: Kyeong Yoo, netfilter-devel@vger.kernel.org
On Tue, Aug 04, 2015 at 11:25:11AM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Mon, Aug 03, 2015 at 04:04:46AM +0000, Kyeong Yoo wrote:
> > > I found this is useful for me to match multiple DSCP values in a rule.
> > >
> > > For example, if you want to handle traffic with a list of DSCP same way,
> > > instead of using this:
> > >
> > > -A FORWARD ...cond1... -m dscp --dscp-class AF11 -j TARGET
> > > -A FORWARD ...cond1... -m dscp --dscp-class AF21 -j TARGET
> > > -A FORWARD ...cond1... -m dscp --dscp-class AF31 -j TARGET
> > > -A FORWARD ...cond2... -m dscp --dscp 10 -j TARGET
> > > -A FORWARD ...cond2... -m dscp --dscp 20 -j TARGET
> > >
> > > you can use:
> > >
> > > -A FORWARD ...cond1... -m dscp --dscp-multi AF11,AF21,AF31 -j TARGET
> > > -A FORWARD ...cond2... -m dscp --dscp-multi 10,20 -j TARGET
> >
> > We support multiple matches in a rule for long time already:
> >
> > -A FORWARD ...cond1... -m dscp --dscp-class AF11 \
> > -m dscp --dscp-class AF21 \
> > -m dscp --dscp-class AF31 \
>
> Yes, but that won't work since this is foo && bar, not foo || bar.
Oh I see. I don't like this combo updates, we may keep receiving
patches to do the same thing for other matches in iptables.
nftables resolves this problem through dictionaries, please have a
look at that.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-08-04 9:29 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-08-03 4:04 New multiple DSCP match by "-m dscp --dscp-multi value,value,..." Kyeong Yoo
2015-08-04 9:19 ` Pablo Neira Ayuso
2015-08-04 9:25 ` Florian Westphal
2015-08-04 9:35 ` Pablo Neira Ayuso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).