cmp.c

00001 /*
00002  * lib/route/cls/ematch/cmp.c   Simple packet data comparison ematch
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup ematch
00014  * @defgroup em_cmp Simple packet data comparison
00015  *
00016  * @{
00017  */
00018 
00019 #include <netlink-local.h>
00020 #include <netlink-tc.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/route/cls/ematch.h>
00023 #include <linux/tc_ematch/tc_em_cmp.h>
00024 
00025 void rtnl_ematch_cmp_set(struct rtnl_ematch *e, struct tcf_em_cmp *cfg)
00026 {
00027         memcpy(rtnl_ematch_data(e), cfg, sizeof(*cfg));
00028 }
00029 
00030 struct tcf_em_cmp *rtnl_ematch_cmp_get(struct rtnl_ematch *e)
00031 {
00032         return rtnl_ematch_data(e);
00033 }
00034 
00035 static int cmp_parse(struct rtnl_ematch *e, void *data, size_t len)
00036 {
00037         memcpy(rtnl_ematch_data(e), data, len);
00038 
00039         return 0;
00040 }
00041 
00042 static const char *align_txt[] = {
00043         [TCF_EM_ALIGN_U8] = "u8",
00044         [TCF_EM_ALIGN_U16] = "u16",
00045         [TCF_EM_ALIGN_U32] = "u32"
00046 };
00047 
00048 static const char *layer_txt[] = {
00049         [TCF_LAYER_LINK] = "eth",
00050         [TCF_LAYER_NETWORK] = "ip",
00051         [TCF_LAYER_TRANSPORT] = "tcp"
00052 };
00053 
00054 static const char *operand_txt[] = {
00055         [TCF_EM_OPND_EQ] = "=",
00056         [TCF_EM_OPND_LT] = "<",
00057         [TCF_EM_OPND_GT] = ">",
00058 };
00059 
00060 static void cmp_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
00061 {
00062         struct tcf_em_cmp *cmp = rtnl_ematch_data(e);
00063 
00064         if (cmp->flags & TCF_EM_CMP_TRANS)
00065                 nl_dump(p, "ntoh%c(", (cmp->align == TCF_EM_ALIGN_U32) ? 'l' : 's');
00066 
00067         nl_dump(p, "%s at %s+%u",
00068                 align_txt[cmp->align], layer_txt[cmp->layer], cmp->off);
00069 
00070         if (cmp->mask)
00071                 nl_dump(p, " & 0x%x", cmp->mask);
00072 
00073         if (cmp->flags & TCF_EM_CMP_TRANS)
00074                 nl_dump(p, ")");
00075 
00076         nl_dump(p, " %s %u", operand_txt[cmp->opnd], cmp->val);
00077 }
00078 
00079 static struct rtnl_ematch_ops cmp_ops = {
00080         .eo_kind        = TCF_EM_CMP,
00081         .eo_name        = "cmp",
00082         .eo_minlen      = sizeof(struct tcf_em_cmp),
00083         .eo_datalen     = sizeof(struct tcf_em_cmp),
00084         .eo_parse       = cmp_parse,
00085         .eo_dump        = cmp_dump,
00086 };
00087 
00088 static void __init cmp_init(void)
00089 {
00090         rtnl_ematch_register(&cmp_ops);
00091 }
00092 
00093 /** @} */