Home | History | Annotate | Download | only in ematch
      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 (at) 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 /** @} */
    117