144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/cls_api.c Classifier Object 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup cls 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup cls_obj Classifier Object 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-tc.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/tc.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/classifier.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/classifier-modules.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/link.h> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @cond SKIP */ 2844d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1) 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2) 3044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @endcond */ 3144d362409d5469aed47d19e7908d19bd194493aThomas Graf 3244d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void cls_free_data(struct nl_object *obj) 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls *cls = (struct rtnl_cls *) obj; 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls_ops *cops; 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf tca_free_data((struct rtnl_tca *) cls); 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf 3944d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_cls_lookup_ops(cls); 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cops && cops->co_free_data) 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf cops->co_free_data(cls); 42ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 43ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf nl_data_free(cls->c_subdata); 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf 4644d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int cls_clone(struct nl_object *_dst, struct nl_object *_src) 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls *dst = nl_object_priv(_dst); 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls *src = nl_object_priv(_src); 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls_ops *cops; 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf err = tca_clone((struct rtnl_tca *) dst, (struct rtnl_tca *) src); 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf 57ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (src->c_subdata) { 58ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (!(dst->c_subdata = nl_data_clone(src->c_subdata))) { 59ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf err = -NLE_NOMEM; 60ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf goto errout; 61ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf } 62ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf } 63ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_cls_lookup_ops(src); 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cops && cops->co_clone) 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf err = cops->co_clone(dst, src); 6744d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 6944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf 71d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void cls_dump_line(struct nl_object *obj, struct nl_dump_params *p) 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf char buf[32]; 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls *cls = (struct rtnl_cls *) obj; 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls_ops *cops; 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf 77d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf tca_dump_line((struct rtnl_tca *) cls, "cls", p); 7844d362409d5469aed47d19e7908d19bd194493aThomas Graf 79d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, " prio %u protocol %s", cls->c_prio, 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf))); 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_cls_lookup_ops(cls); 83d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf if (cops && cops->co_dump[NL_DUMP_LINE]) 84d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf cops->co_dump[NL_DUMP_LINE](cls, p); 85d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 8644d362409d5469aed47d19e7908d19bd194493aThomas Graf} 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf 88d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void cls_dump_details(struct nl_object *obj, struct nl_dump_params *p) 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls *cls = (struct rtnl_cls *) obj; 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls_ops *cops; 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf 93d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf cls_dump_line(obj, p); 94d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf tca_dump_details((struct rtnl_tca *) cls, p); 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_cls_lookup_ops(cls); 97d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf if (cops && cops->co_dump[NL_DUMP_DETAILS]) 98d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf cops->co_dump[NL_DUMP_DETAILS](cls, p); 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf else 100d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "no options\n"); 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf 103d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Grafstatic void cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls *cls = (struct rtnl_cls *) obj; 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_cls_ops *cops; 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf 108d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf cls_dump_details(obj, p); 109d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf tca_dump_stats((struct rtnl_tca *) cls, p); 110d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf nl_dump(p, "\n"); 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_cls_lookup_ops(cls); 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cops && cops->co_dump[NL_DUMP_STATS]) 114d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf cops->co_dump[NL_DUMP_STATS](cls, p); 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Allocation/Freeing 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct rtnl_cls *rtnl_cls_alloc(void) 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf return (struct rtnl_cls *) nl_object_alloc(&cls_obj_ops); 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf 12744d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_cls_put(struct rtnl_cls *cls) 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_object_put((struct nl_object *) cls); 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 13144d362409d5469aed47d19e7908d19bd194493aThomas Graf 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attributes 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf 14044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_cls_set_ifindex(struct rtnl_cls *f, int ifindex) 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf tca_set_ifindex((struct rtnl_tca *) f, ifindex); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf 145ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Grafint rtnl_cls_get_ifindex(struct rtnl_cls *cls) 146ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf{ 147ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return cls->c_ifindex; 148ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf} 149ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 15044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_cls_set_handle(struct rtnl_cls *f, uint32_t handle) 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf tca_set_handle((struct rtnl_tca *) f, handle); 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf 15544d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid rtnl_cls_set_parent(struct rtnl_cls *f, uint32_t parent) 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf tca_set_parent((struct rtnl_tca *) f, parent); 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf 160ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Grafuint32_t rtnl_cls_get_parent(struct rtnl_cls *cls) 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 162ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return cls->c_parent; 163ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf} 164ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 165ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Grafint rtnl_cls_set_kind(struct rtnl_cls *cls, const char *kind) 166ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf{ 167ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (cls->ce_mask & TCA_ATTR_KIND) 168ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return -NLE_EXIST; 169ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 170ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf tca_set_kind((struct rtnl_tca *) cls, kind); 171ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 172ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf /* Force allocation of data */ 173ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf rtnl_cls_data(cls); 174f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Graf 175f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Graf return 0; 176f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Graf} 177f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Graf 178f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Grafstruct rtnl_cls_ops *rtnl_cls_get_ops(struct rtnl_cls *cls) 179f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Graf{ 180f42f195a80ffb7a5dcc355a56b8fe229692718e5Thomas Graf return cls->c_ops; 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf 1835d92f9c03d85cefee5afe7f40d7ea69dfde4cf77Thomas Grafvoid rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio) 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf cls->c_prio = prio; 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf cls->ce_mask |= CLS_ATTR_PRIO; 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1895d92f9c03d85cefee5afe7f40d7ea69dfde4cf77Thomas Grafuint16_t rtnl_cls_get_prio(struct rtnl_cls *cls) 19044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cls->ce_mask & CLS_ATTR_PRIO) 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf return cls->c_prio; 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf else 19444d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf 1975d92f9c03d85cefee5afe7f40d7ea69dfde4cf77Thomas Grafvoid rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol) 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf cls->c_protocol = protocol; 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf cls->ce_mask |= CLS_ATTR_PROTOCOL; 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf 2035d92f9c03d85cefee5afe7f40d7ea69dfde4cf77Thomas Grafuint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls) 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cls->ce_mask & CLS_ATTR_PROTOCOL) 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf return cls->c_protocol; 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf else 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf return ETH_P_ALL; 20944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf 211ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Grafvoid *rtnl_cls_data(struct rtnl_cls *cls) 212ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf{ 213ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (!cls->c_subdata) { 214ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf struct rtnl_cls_ops *ops = cls->c_ops; 215ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 216ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (!ops) { 217ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (!cls->c_kind[0]) 218ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf BUG(); 219ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 220ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf ops = __rtnl_cls_lookup_ops(cls->c_kind); 221ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (ops == NULL) 222ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return NULL; 223ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 224ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf cls->c_ops = ops; 225ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf } 226ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 227ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (!ops->co_size) 228ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf BUG(); 229ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 230ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf if (!(cls->c_subdata = nl_data_alloc(NULL, ops->co_size))) 231ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return NULL; 232ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf } 233ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 234ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf return nl_data_get(cls->c_subdata); 235ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf} 236ef858fb492dfe98e3ae194264fbc73649cf8493aThomas Graf 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf 23944d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_object_ops cls_obj_ops = { 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_name = "route/cls", 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_size = sizeof(struct rtnl_cls), 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_free_data = cls_free_data, 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_clone = cls_clone, 244d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf .oo_dump = { 245d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_LINE] = cls_dump_line, 246d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_DETAILS] = cls_dump_details, 247d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf [NL_DUMP_STATS] = cls_dump_stats, 248d84430702496f617c01c5e2d27d0e82e02390bb7Thomas Graf }, 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_compare = tca_compare, 25044d362409d5469aed47d19e7908d19bd194493aThomas Graf .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE), 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf 25344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 254