Tizen 2.1 base
[platform/upstream/libnl2.git] / lib / route / cls / ematch / cmp.c
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
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
31 struct tcf_em_cmp *rtnl_ematch_cmp_get(struct rtnl_ematch *ematch)
32 {
33         return rtnl_ematch_data(ematch);
34 }
35
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
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
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
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
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
106 static void __init cmp_init(void)
107 {
108         rtnl_ematch_register(&cmp_ops);
109 }
110
111 static void __exit cmp_exit(void)
112 {
113         rtnl_ematch_unregister(&cmp_ops);
114 }
115
116 /** @} */