Home | History | Annotate | Download | only in act
      1 /*
      2  * lib/route/cls/mirred.c		mirred action
      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) 2013 Cong Wang <xiyou.wangcong (at) gmail.com>
     10  */
     11 
     12 /**
     13  * @ingroup act
     14  * @defgroup act_mirred Mirror and Redirect
     15  *
     16  * @{
     17  */
     18 
     19 #include <netlink-private/netlink.h>
     20 #include <netlink-private/tc.h>
     21 #include <netlink/netlink.h>
     22 #include <netlink/attr.h>
     23 #include <netlink/utils.h>
     24 #include <netlink-private/route/tc-api.h>
     25 #include <netlink/route/act/mirred.h>
     26 
     27 static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
     28 	[TCA_MIRRED_PARMS]      = { .minlen = sizeof(struct tc_mirred) },
     29 };
     30 
     31 static int mirred_msg_parser(struct rtnl_tc *tc, void *data)
     32 {
     33 	struct rtnl_mirred *u = data;
     34 	struct nlattr *tb[TCA_MIRRED_MAX + 1];
     35 	int err;
     36 
     37 	err = tca_parse(tb, TCA_MIRRED_MAX, tc, mirred_policy);
     38 	if (err < 0)
     39 		return err;
     40 
     41 	if (!tb[TCA_MIRRED_PARMS])
     42 		return -NLE_MISSING_ATTR;
     43 
     44 	nla_memcpy(&u->m_parm, tb[TCA_MIRRED_PARMS], sizeof(u->m_parm));
     45 	return 0;
     46 }
     47 
     48 static void mirred_free_data(struct rtnl_tc *tc, void *data)
     49 {
     50 }
     51 
     52 static int mirred_clone(void *_dst, void *_src)
     53 {
     54 	struct rtnl_mirred *dst = _dst, *src = _src;
     55 
     56 	memcpy(&dst->m_parm, &src->m_parm, sizeof(src->m_parm));
     57 	return 0;
     58 }
     59 
     60 static void mirred_dump_line(struct rtnl_tc *tc, void *data,
     61 			  struct nl_dump_params *p)
     62 {
     63 	struct rtnl_mirred *u = data;
     64 	if (!u)
     65 		return;
     66 
     67 	nl_dump(p, " index %u", u->m_parm.ifindex);
     68 
     69 	if (u->m_parm.eaction == TCA_EGRESS_MIRROR)
     70 		nl_dump(p, " egress mirror");
     71 	else if (u->m_parm.eaction == TCA_EGRESS_REDIR)
     72 		nl_dump(p, " egress redirect");
     73 
     74 	switch(u->m_parm.action) {
     75 	case TC_ACT_UNSPEC:
     76 		nl_dump(p, " unspecified");
     77 		break;
     78 	case TC_ACT_PIPE:
     79 		nl_dump(p, " pipe");
     80 		break;
     81 	case TC_ACT_STOLEN:
     82 		nl_dump(p, " stolen");
     83 		break;
     84 	case TC_ACT_SHOT:
     85 		nl_dump(p, " shot");
     86 		break;
     87 	case TC_ACT_QUEUED:
     88 		nl_dump(p, " queued");
     89 		break;
     90 	case TC_ACT_REPEAT:
     91 		nl_dump(p, " repeat");
     92 		break;
     93 	}
     94 }
     95 
     96 static void mirred_dump_details(struct rtnl_tc *tc, void *data,
     97 			     struct nl_dump_params *p)
     98 {
     99 }
    100 
    101 static void mirred_dump_stats(struct rtnl_tc *tc, void *data,
    102 			   struct nl_dump_params *p)
    103 {
    104 	struct rtnl_mirred *u = data;
    105 
    106 	if (!u)
    107 		return;
    108 	/* TODO */
    109 }
    110 
    111 
    112 static int mirred_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
    113 {
    114 	struct rtnl_mirred *u = data;
    115 
    116 	if (!u)
    117 		return 0;
    118 
    119 	NLA_PUT(msg, TCA_MIRRED_PARMS, sizeof(u->m_parm), &u->m_parm);
    120 	return 0;
    121 
    122 nla_put_failure:
    123 	return -NLE_NOMEM;
    124 }
    125 
    126 /**
    127  * @name Attribute Modifications
    128  * @{
    129  */
    130 
    131 int rtnl_mirred_set_action(struct rtnl_act *act, int action)
    132 {
    133 	struct rtnl_mirred *u;
    134 
    135 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
    136 		return -NLE_NOMEM;
    137 
    138 	if (action > TCA_INGRESS_MIRROR || action < TCA_EGRESS_REDIR)
    139 		return -NLE_INVAL;
    140 
    141 	switch (action) {
    142 	case TCA_EGRESS_MIRROR:
    143 	case TCA_EGRESS_REDIR:
    144 		u->m_parm.eaction = action;
    145 		break;
    146 	case TCA_INGRESS_REDIR:
    147 	case TCA_INGRESS_MIRROR:
    148 	default:
    149 		return NLE_OPNOTSUPP;
    150 	}
    151 	return 0;
    152 }
    153 
    154 int rtnl_mirred_get_action(struct rtnl_act *act)
    155 {
    156 	struct rtnl_mirred *u;
    157 
    158 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
    159 		return -NLE_NOMEM;
    160 	return u->m_parm.eaction;
    161 }
    162 
    163 int rtnl_mirred_set_ifindex(struct rtnl_act *act, uint32_t ifindex)
    164 {
    165 	struct rtnl_mirred *u;
    166 
    167 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
    168 		return -NLE_NOMEM;
    169 
    170 	u->m_parm.ifindex = ifindex;
    171 	return 0;
    172 }
    173 
    174 uint32_t rtnl_mirred_get_ifindex(struct rtnl_act *act)
    175 {
    176 	struct rtnl_mirred *u;
    177 
    178 	if ((u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
    179 		return u->m_parm.ifindex;
    180 	return 0;
    181 }
    182 
    183 int rtnl_mirred_set_policy(struct rtnl_act *act, int policy)
    184 {
    185 	struct rtnl_mirred *u;
    186 
    187 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
    188 		return -NLE_NOMEM;
    189 
    190 	if (policy > TC_ACT_REPEAT || policy < TC_ACT_OK)
    191 		return -NLE_INVAL;
    192 
    193 	switch (u->m_parm.eaction) {
    194 	case TCA_EGRESS_MIRROR:
    195 	case TCA_EGRESS_REDIR:
    196 		u->m_parm.action = policy;
    197 		break;
    198 	case TCA_INGRESS_REDIR:
    199 	case TCA_INGRESS_MIRROR:
    200 	default:
    201 		return NLE_OPNOTSUPP;
    202 	}
    203 	return 0;
    204 }
    205 
    206 int rtnl_mirred_get_policy(struct rtnl_act *act)
    207 {
    208 	struct rtnl_mirred *u;
    209 
    210 	if (!(u = (struct rtnl_mirred *) rtnl_tc_data(TC_CAST(act))))
    211 		return -NLE_NOMEM;
    212 	return u->m_parm.action;
    213 }
    214 
    215 /** @} */
    216 
    217 static struct rtnl_tc_ops mirred_ops = {
    218 	.to_kind		= "mirred",
    219 	.to_type		= RTNL_TC_TYPE_ACT,
    220 	.to_size		= sizeof(struct rtnl_mirred),
    221 	.to_msg_parser		= mirred_msg_parser,
    222 	.to_free_data		= mirred_free_data,
    223 	.to_clone		= mirred_clone,
    224 	.to_msg_fill		= mirred_msg_fill,
    225 	.to_dump = {
    226 	    [NL_DUMP_LINE]	= mirred_dump_line,
    227 	    [NL_DUMP_DETAILS]	= mirred_dump_details,
    228 	    [NL_DUMP_STATS]	= mirred_dump_stats,
    229 	},
    230 };
    231 
    232 static void __init mirred_init(void)
    233 {
    234 	rtnl_tc_register(&mirred_ops);
    235 }
    236 
    237 static void __exit mirred_exit(void)
    238 {
    239 	rtnl_tc_unregister(&mirred_ops);
    240 }
    241 
    242 /** @} */
    243