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 nl_data_free(cls->c_subdata);
00044 }
00045
00046 static int cls_clone(struct nl_object *_dst, struct nl_object *_src)
00047 {
00048 struct rtnl_cls *dst = nl_object_priv(_dst);
00049 struct rtnl_cls *src = nl_object_priv(_src);
00050 struct rtnl_cls_ops *cops;
00051 int err;
00052
00053 err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src);
00054 if (err < 0)
00055 goto errout;
00056
00057 if (src->c_subdata) {
00058 if (!(dst->c_subdata = nl_data_clone(src->c_subdata))) {
00059 err = -NLE_NOMEM;
00060 goto errout;
00061 }
00062 }
00063
00064 cops = rtnl_cls_lookup_ops(src);
00065 if (cops && cops->co_clone)
00066 err = cops->co_clone(dst, src);
00067 errout:
00068 return err;
00069 }
00070
00071 static void cls_dump_line(struct nl_object *obj, struct nl_dump_params *p)
00072 {
00073 char buf[32];
00074 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00075 struct rtnl_cls_ops *cops;
00076
00077 tca_dump_line((struct rtnl_tca *) cls, "cls", p);
00078
00079 nl_dump(p, " prio %u protocol %s", cls->c_prio,
00080 nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
00081
00082 cops = rtnl_cls_lookup_ops(cls);
00083 if (cops && cops->co_dump[NL_DUMP_LINE])
00084 cops->co_dump[NL_DUMP_LINE](cls, p);
00085 nl_dump(p, "\n");
00086 }
00087
00088 static void cls_dump_details(struct nl_object *obj, struct nl_dump_params *p)
00089 {
00090 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00091 struct rtnl_cls_ops *cops;
00092
00093 cls_dump_line(obj, p);
00094 tca_dump_details((struct rtnl_tca *) cls, p);
00095
00096 cops = rtnl_cls_lookup_ops(cls);
00097 if (cops && cops->co_dump[NL_DUMP_DETAILS])
00098 cops->co_dump[NL_DUMP_DETAILS](cls, p);
00099 else
00100 nl_dump(p, "no options\n");
00101 }
00102
00103 static void cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00104 {
00105 struct rtnl_cls *cls = (struct rtnl_cls *) obj;
00106 struct rtnl_cls_ops *cops;
00107
00108 cls_dump_details(obj, p);
00109 tca_dump_stats((struct rtnl_tca *) cls, p);
00110 nl_dump(p, "\n");
00111
00112 cops = rtnl_cls_lookup_ops(cls);
00113 if (cops && cops->co_dump[NL_DUMP_STATS])
00114 cops->co_dump[NL_DUMP_STATS](cls, p);
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 int rtnl_cls_get_ifindex(struct rtnl_cls *cls)
00146 {
00147 return cls->c_ifindex;
00148 }
00149
00150 void rtnl_cls_set_handle(struct rtnl_cls *f, uint32_t handle)
00151 {
00152 tca_set_handle((struct rtnl_tca *) f, handle);
00153 }
00154
00155 void rtnl_cls_set_parent(struct rtnl_cls *f, uint32_t parent)
00156 {
00157 tca_set_parent((struct rtnl_tca *) f, parent);
00158 }
00159
00160 uint32_t rtnl_cls_get_parent(struct rtnl_cls *cls)
00161 {
00162 return cls->c_parent;
00163 }
00164
00165 int rtnl_cls_set_kind(struct rtnl_cls *cls, const char *kind)
00166 {
00167 if (cls->ce_mask & TCA_ATTR_KIND)
00168 return -NLE_EXIST;
00169
00170 tca_set_kind((struct rtnl_tca *) cls, kind);
00171
00172
00173 rtnl_cls_data(cls);
00174
00175 return 0;
00176 }
00177
00178 struct rtnl_cls_ops *rtnl_cls_get_ops(struct rtnl_cls *cls)
00179 {
00180 return cls->c_ops;
00181 }
00182
00183 void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
00184 {
00185 cls->c_prio = prio;
00186 cls->ce_mask |= CLS_ATTR_PRIO;
00187 }
00188
00189 uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
00190 {
00191 if (cls->ce_mask & CLS_ATTR_PRIO)
00192 return cls->c_prio;
00193 else
00194 return 0;
00195 }
00196
00197 void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
00198 {
00199 cls->c_protocol = protocol;
00200 cls->ce_mask |= CLS_ATTR_PROTOCOL;
00201 }
00202
00203 uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
00204 {
00205 if (cls->ce_mask & CLS_ATTR_PROTOCOL)
00206 return cls->c_protocol;
00207 else
00208 return ETH_P_ALL;
00209 }
00210
00211 void *rtnl_cls_data(struct rtnl_cls *cls)
00212 {
00213 if (!cls->c_subdata) {
00214 struct rtnl_cls_ops *ops = cls->c_ops;
00215
00216 if (!ops) {
00217 if (!cls->c_kind[0])
00218 BUG();
00219
00220 ops = __rtnl_cls_lookup_ops(cls->c_kind);
00221 if (ops == NULL)
00222 return NULL;
00223
00224 cls->c_ops = ops;
00225 }
00226
00227 if (!ops->co_size)
00228 BUG();
00229
00230 if (!(cls->c_subdata = nl_data_alloc(NULL, ops->co_size)))
00231 return NULL;
00232 }
00233
00234 return nl_data_get(cls->c_subdata);
00235 }
00236
00237
00238
00239 struct nl_object_ops cls_obj_ops = {
00240 .oo_name = "route/cls",
00241 .oo_size = sizeof(struct rtnl_cls),
00242 .oo_free_data = cls_free_data,
00243 .oo_clone = cls_clone,
00244 .oo_dump = {
00245 [NL_DUMP_LINE] = cls_dump_line,
00246 [NL_DUMP_DETAILS] = cls_dump_details,
00247 [NL_DUMP_STATS] = cls_dump_stats,
00248 },
00249 .oo_compare = tca_compare,
00250 .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
00251 };
00252
00253