00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <netlink-local.h>
00019 #include <netlink-tc.h>
00020 #include <netlink/netlink.h>
00021 #include <netlink/utils.h>
00022 #include <netlink/route/tc.h>
00023 #include <netlink/route/classifier.h>
00024 #include <netlink/route/classifier-modules.h>
00025 #include <netlink/route/link.h>
00026
00027
00028 #define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
00029 #define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
00030
00031
00032 static void cls_free_data(struct nl_object *obj)
00033 {
00034 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00035 struct rtnl_cls_ops *cops;
00036
00037 tca_free_data((struct rtnl_tca *) cls);
00038
00039 cops = rtnl_cls_lookup_ops(cls);
00040 if (cops && cops->co_free_data)
00041 cops->co_free_data(cls);
00042 }
00043
00044 static int cls_clone(struct nl_object *_dst, struct nl_object *_src)
00045 {
00046 struct rtnl_cls *dst = nl_object_priv(_dst);
00047 struct rtnl_cls *src = nl_object_priv(_src);
00048 struct rtnl_cls_ops *cops;
00049 int err;
00050
00051 err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
00052 if (err < 0)
00053 goto errout;
00054
00055 cops = rtnl_cls_lookup_ops(src);
00056 if (cops && cops->co_clone)
00057 err = cops->co_clone(dst, src);
00058 errout:
00059 return err;
00060 }
00061
00062 static int cls_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
00063 {
00064 char buf[32];
00065 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00066 struct rtnl_cls_ops *cops;
00067 int line;
00068
00069 line = tca_dump_brief((struct rtnl_tca *) cls, "cls", p, 0);
00070
00071 dp_dump(p, " prio %u protocol %s", cls->c_prio,
00072 nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
00073
00074 cops = rtnl_cls_lookup_ops(cls);
00075 if (cops && cops->co_dump[NL_DUMP_BRIEF])
00076 line = cops->co_dump[NL_DUMP_BRIEF](cls, p, line);
00077 dp_dump(p, "\n");
00078
00079 return line;
00080 }
00081
00082 static int cls_dump_full(struct nl_object *obj, struct nl_dump_params *p)
00083 {
00084 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00085 struct rtnl_cls_ops *cops;
00086 int line;
00087
00088 line = cls_dump_brief(obj, p);
00089 line = tca_dump_full((struct rtnl_tca *) cls, p, line);
00090
00091 cops = rtnl_cls_lookup_ops(cls);
00092 if (cops && cops->co_dump[NL_DUMP_FULL])
00093 line = cops->co_dump[NL_DUMP_FULL](cls, p, line);
00094 else
00095 dp_dump(p, "no options\n");
00096
00097 return line;
00098 }
00099
00100 static int cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00101 {
00102 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00103 struct rtnl_cls_ops *cops;
00104 int line;
00105
00106 line = cls_dump_full(obj, p);
00107 line = tca_dump_stats((struct rtnl_tca *) cls, p, line);
00108 dp_dump(p, "\n");
00109
00110 cops = rtnl_cls_lookup_ops(cls);
00111 if (cops && cops->co_dump[NL_DUMP_STATS])
00112 line = cops->co_dump[NL_DUMP_STATS](cls, p, line);
00113
00114 return line;
00115 }
00116
00117
00118
00119
00120
00121
00122 struct rtnl_cls *rtnl_cls_alloc(void)
00123 {
00124 return (struct rtnl_cls *) nl_object_alloc(&cls_obj_ops);
00125 }
00126
00127 void rtnl_cls_put(struct rtnl_cls *cls)
00128 {
00129 nl_object_put((struct nl_object *) cls);
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 void rtnl_cls_set_ifindex(struct rtnl_cls *f, int ifindex)
00141 {
00142 tca_set_ifindex((struct rtnl_tca *) f, ifindex);
00143 }
00144
00145 void rtnl_cls_set_handle(struct rtnl_cls *f, uint32_t handle)
00146 {
00147 tca_set_handle((struct rtnl_tca *) f, handle);
00148 }
00149
00150 void rtnl_cls_set_parent(struct rtnl_cls *f, uint32_t parent)
00151 {
00152 tca_set_parent((struct rtnl_tca *) f, parent);
00153 }
00154
00155 void rtnl_cls_set_kind(struct rtnl_cls *f, const char *kind)
00156 {
00157 tca_set_kind((struct rtnl_tca *) f, kind);
00158 f->c_ops = __rtnl_cls_lookup_ops(kind);
00159 }
00160
00161 void rtnl_cls_set_prio(struct rtnl_cls *cls, int prio)
00162 {
00163 cls->c_prio = prio;
00164 cls->ce_mask |= CLS_ATTR_PRIO;
00165 }
00166
00167 int rtnl_cls_get_prio(struct rtnl_cls *cls)
00168 {
00169 if (cls->ce_mask & CLS_ATTR_PRIO)
00170 return cls->c_prio;
00171 else
00172 return 0;
00173 }
00174
00175 void rtnl_cls_set_protocol(struct rtnl_cls *cls, int protocol)
00176 {
00177 cls->c_protocol = protocol;
00178 cls->ce_mask |= CLS_ATTR_PROTOCOL;
00179 }
00180
00181 int rtnl_cls_get_protocol(struct rtnl_cls *cls)
00182 {
00183 if (cls->ce_mask & CLS_ATTR_PROTOCOL)
00184 return cls->c_protocol;
00185 else
00186 return ETH_P_ALL;
00187 }
00188
00189
00190
00191 struct nl_object_ops cls_obj_ops = {
00192 .oo_name = "route/cls",
00193 .oo_size = sizeof(struct rtnl_cls),
00194 .oo_free_data = cls_free_data,
00195 .oo_clone = cls_clone,
00196 .oo_dump[NL_DUMP_BRIEF] = cls_dump_brief,
00197 .oo_dump[NL_DUMP_FULL] = cls_dump_full,
00198 .oo_dump[NL_DUMP_STATS] = cls_dump_stats,
00199 .oo_compare = tca_compare,
00200 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
00201 };
00202
00203