1 /*
2 * lib/route/cls/ematch/cmp.c Simple packet data comparison ematch
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2008-2009 Thomas Graf <tgraf@suug.ch>
10 */
11
12 /**
13 * @ingroup ematch
14 * @defgroup em_cmp Simple packet data comparison
15 *
16 * @{
17 */
18
19 #include <netlink-local.h>
20 #include <netlink-tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/route/cls/ematch.h>
23 #include <linux/tc_ematch/tc_em_cmp.h>
24
rtnl_ematch_cmp_set(struct rtnl_ematch * ematch,struct tcf_em_cmp * cfg)25 void rtnl_ematch_cmp_set(struct rtnl_ematch *ematch,
26 struct tcf_em_cmp *cfg)
27 {
28 memcpy(rtnl_ematch_data(ematch), cfg, sizeof(*cfg));
29 }
30
rtnl_ematch_cmp_get(struct rtnl_ematch * ematch)31 struct tcf_em_cmp *rtnl_ematch_cmp_get(struct rtnl_ematch *ematch)
32 {
33 return rtnl_ematch_data(ematch);
34 }
35
align_txt(struct tcf_em_cmp * cmp)36 static const char *align_txt(struct tcf_em_cmp *cmp)
37 {
38 switch (cmp->align) {
39 case TCF_EM_ALIGN_U8:
40 return "u8";
41 case TCF_EM_ALIGN_U16:
42 return (cmp->flags & TCF_EM_CMP_TRANS) ? "h16" : "u16";
43 case TCF_EM_ALIGN_U32:
44 return (cmp->flags & TCF_EM_CMP_TRANS) ? "h32" : "u32";
45 default:
46 return (cmp->flags & TCF_EM_CMP_TRANS) ? "h?" : "u?";
47 }
48 }
49
layer_txt(struct tcf_em_cmp * cmp)50 static const char *layer_txt(struct tcf_em_cmp *cmp)
51 {
52 switch (cmp->layer) {
53 case TCF_LAYER_LINK:
54 return "link";
55 case TCF_LAYER_NETWORK:
56 return "network";
57 case TCF_LAYER_TRANSPORT:
58 return "transport";
59 default:
60 return "?";
61 }
62 }
63
relation_txt(struct tcf_em_cmp * cmp)64 static const char *relation_txt(struct tcf_em_cmp *cmp)
65 {
66 switch (cmp->opnd) {
67 case TCF_EM_OPND_EQ:
68 return "eq";
69 case TCF_EM_OPND_LT:
70 return "lt";
71 case TCF_EM_OPND_GT:
72 return "gt";
73 default:
74 return "?";
75 }
76 }
77
cmp_parse(struct rtnl_ematch * m,void * data,size_t len)78 static int cmp_parse(struct rtnl_ematch *m, void *data, size_t len)
79 {
80 memcpy(rtnl_ematch_data(m), data, len);
81
82 return 0;
83 }
84
cmp_dump(struct rtnl_ematch * m,struct nl_dump_params * p)85 static void cmp_dump(struct rtnl_ematch *m, struct nl_dump_params *p)
86 {
87 struct tcf_em_cmp *cmp = rtnl_ematch_data(m);
88
89 nl_dump(p, "%s at %s+%u ",
90 align_txt(cmp), layer_txt(cmp), cmp->off);
91
92 if (cmp->mask)
93 nl_dump(p, "& 0x%x ", cmp->mask);
94
95 nl_dump(p, "%s %u", relation_txt(cmp), cmp->val);
96 }
97
98 static struct rtnl_ematch_ops cmp_ops = {
99 .eo_kind = TCF_EM_CMP,
100 .eo_name = "cmp",
101 .eo_datalen = sizeof(struct tcf_em_cmp),
102 .eo_parse = cmp_parse,
103 .eo_dump = cmp_dump,
104 };
105
cmp_init(void)106 static void __init cmp_init(void)
107 {
108 rtnl_ematch_register(&cmp_ops);
109 }
110
cmp_exit(void)111 static void __exit cmp_exit(void)
112 {
113 rtnl_ematch_unregister(&cmp_ops);
114 }
115
116 /** @} */
117