144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/route/class.c Queueing Classes 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 * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 1344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @ingroup tc 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup class Queueing Classes 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/route/tc.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/class.h> 2344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/class-modules.h> 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/qdisc.h> 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/route/classifier.h> 2644d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2744d362409d5469aed47d19e7908d19bd194493aThomas Graf 2844d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_class_ops; 2944d362409d5469aed47d19e7908d19bd194493aThomas Graf 3044d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic int class_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 313040a1d6254465bed9e44e4d1bf279c2c50cd16aThomas Graf struct nlmsghdr *n, struct nl_parser_param *pp) 3244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 3344d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 3444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_class *class; 3544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_class_ops *cops; 3644d362409d5469aed47d19e7908d19bd194493aThomas Graf 3744d362409d5469aed47d19e7908d19bd194493aThomas Graf class = rtnl_class_alloc(); 3844d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!class) { 398a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = -NLE_NOMEM; 4044d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 4144d362409d5469aed47d19e7908d19bd194493aThomas Graf } 4244d362409d5469aed47d19e7908d19bd194493aThomas Graf class->ce_msgtype = n->nlmsg_type; 4344d362409d5469aed47d19e7908d19bd194493aThomas Graf 4444d362409d5469aed47d19e7908d19bd194493aThomas Graf err = tca_msg_parser(n, (struct rtnl_tca *) class); 4544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 4644d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout_free; 4744d362409d5469aed47d19e7908d19bd194493aThomas Graf 4844d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_class_lookup_ops(class); 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cops && cops->co_msg_parser) { 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf err = cops->co_msg_parser(class); 5144d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout_free; 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf } 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf err = pp->pp_cb((struct nl_object *) class, pp); 5644d362409d5469aed47d19e7908d19bd194493aThomas Graferrout_free: 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf rtnl_class_put(class); 5844d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 5944d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf 621155370f520cb64657e25153255cf7dc1424317fThomas Grafstatic int class_request_update(struct nl_cache *cache, struct nl_sock *sk) 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 6444d362409d5469aed47d19e7908d19bd194493aThomas Graf struct tcmsg tchdr = { 6544d362409d5469aed47d19e7908d19bd194493aThomas Graf .tcm_family = AF_UNSPEC, 6644d362409d5469aed47d19e7908d19bd194493aThomas Graf .tcm_ifindex = cache->c_iarg1, 6744d362409d5469aed47d19e7908d19bd194493aThomas Graf }; 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf 691155370f520cb64657e25153255cf7dc1424317fThomas Graf return nl_send_simple(sk, RTM_GETTCLASS, NLM_F_DUMP, &tchdr, 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf sizeof(tchdr)); 7144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Addition/Modification 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 7744d362409d5469aed47d19e7908d19bd194493aThomas Graf 788a3efffa5b3fde252675239914118664d36a2c24Thomas Grafstatic int class_build(struct rtnl_class *class, int type, int flags, 798a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 8144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct rtnl_class_ops *cops; 8244d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf 848a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = tca_build_msg((struct rtnl_tca *) class, type, flags, result); 858a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (err < 0) 868a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf cops = rtnl_class_lookup_ops(class); 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (cops && cops->co_get_opts) { 9044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *opts; 9144d362409d5469aed47d19e7908d19bd194493aThomas Graf 9244d362409d5469aed47d19e7908d19bd194493aThomas Graf opts = cops->co_get_opts(class); 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (opts) { 948a3efffa5b3fde252675239914118664d36a2c24Thomas Graf err = nla_put_nested(*result, TCA_OPTIONS, opts); 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf nlmsg_free(opts); 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (err < 0) 9744d362409d5469aed47d19e7908d19bd194493aThomas Graf goto errout; 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf } 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf } 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf 1018a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 10244d362409d5469aed47d19e7908d19bd194493aThomas Graferrout: 1038a3efffa5b3fde252675239914118664d36a2c24Thomas Graf nlmsg_free(*result); 1048a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a netlink message to add a new class 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg class class to add 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 1118a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @arg result Pointer to store resulting message. 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a new netlink message requesting an addition of a class. 11444d362409d5469aed47d19e7908d19bd194493aThomas Graf * The netlink message header isn't fully equipped with all relevant 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf * fields and must be sent out via nl_send_auto_complete() or 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf * supplemented as needed. 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf * 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Common message flags 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf * - NLM_F_REPLACE - replace possibly existing classes 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 1218a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * @return 0 on success or a negative error code. 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1238a3efffa5b3fde252675239914118664d36a2c24Thomas Grafint rtnl_class_build_add_request(struct rtnl_class *class, int flags, 1248a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_msg **result) 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1268a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return class_build(class, RTM_NEWTCLASS, NLM_F_CREATE | flags, result); 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Add a new class 1311155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg class class to delete 13344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg flags additional netlink message flags 13444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Builds a netlink message by calling rtnl_qdisc_build_add_request(), 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf * sends the request to the kernel and waits for the next ACK to be 13744d362409d5469aed47d19e7908d19bd194493aThomas Graf * received and thus blocks until the request has been processed. 13844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Common message flags 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf * - NLM_F_REPLACE - replace possibly existing classes 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf * 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1441155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_class_add(struct nl_sock *sk, struct rtnl_class *class, int flags) 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_msg *msg; 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf int err; 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf 1498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if ((err = rtnl_class_build_add_request(class, flags, &msg)) < 0) 1508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf 152ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf err = nl_send_auto_complete(sk, msg); 153ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf nlmsg_free(msg); 154ef50a38fbd8682a5c9efd559e7db68664977f080Thomas Graf if (err < 0) 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf return err; 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf 157cfcfca070355b246028df60da79813f09ed65755Thomas Graf return wait_for_ack(sk); 15844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf 1602ead49f0d5873628156e50dfed7da14619a4172dolcint rtnl_class_build_delete_request(struct rtnl_class *class, 1612ead49f0d5873628156e50dfed7da14619a4172dolc struct nl_msg **result) 1622ead49f0d5873628156e50dfed7da14619a4172dolc{ 1632ead49f0d5873628156e50dfed7da14619a4172dolc struct nl_msg *msg; 1642ead49f0d5873628156e50dfed7da14619a4172dolc struct tcmsg tchdr; 1652ead49f0d5873628156e50dfed7da14619a4172dolc int required = TCA_ATTR_IFINDEX | TCA_ATTR_PARENT; 1662ead49f0d5873628156e50dfed7da14619a4172dolc 1672ead49f0d5873628156e50dfed7da14619a4172dolc if ((class->ce_mask & required) != required) 1682ead49f0d5873628156e50dfed7da14619a4172dolc BUG(); 1692ead49f0d5873628156e50dfed7da14619a4172dolc 1702ead49f0d5873628156e50dfed7da14619a4172dolc msg = nlmsg_alloc_simple(RTM_DELTCLASS, 0); 1712ead49f0d5873628156e50dfed7da14619a4172dolc if (!msg) 1722ead49f0d5873628156e50dfed7da14619a4172dolc return -NLE_NOMEM; 1732ead49f0d5873628156e50dfed7da14619a4172dolc 1742ead49f0d5873628156e50dfed7da14619a4172dolc tchdr.tcm_family = AF_UNSPEC; 1752ead49f0d5873628156e50dfed7da14619a4172dolc tchdr.tcm_handle = class->c_handle; 1762ead49f0d5873628156e50dfed7da14619a4172dolc tchdr.tcm_parent = class->c_parent; 1772ead49f0d5873628156e50dfed7da14619a4172dolc tchdr.tcm_ifindex = class->c_ifindex; 1782ead49f0d5873628156e50dfed7da14619a4172dolc if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) { 1792ead49f0d5873628156e50dfed7da14619a4172dolc nlmsg_free(msg); 1802ead49f0d5873628156e50dfed7da14619a4172dolc return -NLE_MSGSIZE; 1812ead49f0d5873628156e50dfed7da14619a4172dolc } 1822ead49f0d5873628156e50dfed7da14619a4172dolc 1832ead49f0d5873628156e50dfed7da14619a4172dolc *result = msg; 1842ead49f0d5873628156e50dfed7da14619a4172dolc return 0; 1852ead49f0d5873628156e50dfed7da14619a4172dolc} 1862ead49f0d5873628156e50dfed7da14619a4172dolc 1872ead49f0d5873628156e50dfed7da14619a4172dolc/** 1882ead49f0d5873628156e50dfed7da14619a4172dolc * Delete a class 1892ead49f0d5873628156e50dfed7da14619a4172dolc * @arg sk Netlink socket. 1902ead49f0d5873628156e50dfed7da14619a4172dolc * @arg class class to delete 1912ead49f0d5873628156e50dfed7da14619a4172dolc * 1922ead49f0d5873628156e50dfed7da14619a4172dolc * Builds a netlink message by calling rtnl_class_build_delete_request(), 1932ead49f0d5873628156e50dfed7da14619a4172dolc * sends the request to the kernel and waits for the ACK to be 1942ead49f0d5873628156e50dfed7da14619a4172dolc * received and thus blocks until the request has been processed. 1952ead49f0d5873628156e50dfed7da14619a4172dolc * 1962ead49f0d5873628156e50dfed7da14619a4172dolc * @return 0 on success or a negative error code 1972ead49f0d5873628156e50dfed7da14619a4172dolc */ 1982ead49f0d5873628156e50dfed7da14619a4172dolcint rtnl_class_delete(struct nl_sock *sk, struct rtnl_class *class) 1992ead49f0d5873628156e50dfed7da14619a4172dolc{ 2002ead49f0d5873628156e50dfed7da14619a4172dolc struct nl_msg *msg; 2012ead49f0d5873628156e50dfed7da14619a4172dolc int err; 2022ead49f0d5873628156e50dfed7da14619a4172dolc 2032ead49f0d5873628156e50dfed7da14619a4172dolc if ((err = rtnl_class_build_delete_request(class, &msg)) < 0) 2042ead49f0d5873628156e50dfed7da14619a4172dolc return err; 2052ead49f0d5873628156e50dfed7da14619a4172dolc 2062ead49f0d5873628156e50dfed7da14619a4172dolc err = nl_send_auto_complete(sk, msg); 2072ead49f0d5873628156e50dfed7da14619a4172dolc nlmsg_free(msg); 2082ead49f0d5873628156e50dfed7da14619a4172dolc if (err < 0) 2092ead49f0d5873628156e50dfed7da14619a4172dolc return err; 2102ead49f0d5873628156e50dfed7da14619a4172dolc 2112ead49f0d5873628156e50dfed7da14619a4172dolc return wait_for_ack(sk); 2122ead49f0d5873628156e50dfed7da14619a4172dolc} 2132ead49f0d5873628156e50dfed7da14619a4172dolc 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Cache Management 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Build a class cache including all classes attached to the specified interface 2231155370f520cb64657e25153255cf7dc1424317fThomas Graf * @arg sk Netlink socket. 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ifindex interface index of the link the classes are 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf * attached to. 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new cache, initializes it properly and updates it to 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * include all classes attached to the specified interface. 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf * 23044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The cache or NULL if an error has occured. 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 2321155370f520cb64657e25153255cf7dc1424317fThomas Grafint rtnl_class_alloc_cache(struct nl_sock *sk, int ifindex, 2338a3efffa5b3fde252675239914118664d36a2c24Thomas Graf struct nl_cache **result) 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache * cache; 2368a3efffa5b3fde252675239914118664d36a2c24Thomas Graf int err; 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf cache = nl_cache_alloc(&rtnl_class_ops); 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!cache) 2408a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOMEM; 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf cache->c_iarg1 = ifindex; 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf 2441155370f520cb64657e25153255cf7dc1424317fThomas Graf if (sk && (err = nl_cache_refill(sk, cache)) < 0) { 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_free(cache); 2468a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return err; 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf } 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf 2498a3efffa5b3fde252675239914118664d36a2c24Thomas Graf *result = cache; 2508a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return 0; 25144d362409d5469aed47d19e7908d19bd194493aThomas Graf} 25244d362409d5469aed47d19e7908d19bd194493aThomas Graf 2532ead49f0d5873628156e50dfed7da14619a4172dolc/** 2542ead49f0d5873628156e50dfed7da14619a4172dolc * Look up class by its handle in the provided cache 2552ead49f0d5873628156e50dfed7da14619a4172dolc * @arg cache class cache 2562ead49f0d5873628156e50dfed7da14619a4172dolc * @arg ifindex interface the class is attached to 2572ead49f0d5873628156e50dfed7da14619a4172dolc * @arg handle class handle 2582ead49f0d5873628156e50dfed7da14619a4172dolc * @return pointer to class inside the cache or NULL if no match was found. 2592ead49f0d5873628156e50dfed7da14619a4172dolc */ 2602ead49f0d5873628156e50dfed7da14619a4172dolcstruct rtnl_class *rtnl_class_get(struct nl_cache *cache, int ifindex, 2612ead49f0d5873628156e50dfed7da14619a4172dolc uint32_t handle) 2622ead49f0d5873628156e50dfed7da14619a4172dolc{ 2632ead49f0d5873628156e50dfed7da14619a4172dolc struct rtnl_class *class; 2642ead49f0d5873628156e50dfed7da14619a4172dolc 2652ead49f0d5873628156e50dfed7da14619a4172dolc if (cache->c_ops != &rtnl_class_ops) 2662ead49f0d5873628156e50dfed7da14619a4172dolc return NULL; 2672ead49f0d5873628156e50dfed7da14619a4172dolc 2682ead49f0d5873628156e50dfed7da14619a4172dolc nl_list_for_each_entry(class, &cache->c_items, ce_list) { 2692ead49f0d5873628156e50dfed7da14619a4172dolc if (class->c_handle == handle && class->c_ifindex == ifindex) { 2702ead49f0d5873628156e50dfed7da14619a4172dolc nl_object_get((struct nl_object *) class); 2712ead49f0d5873628156e50dfed7da14619a4172dolc return class; 2722ead49f0d5873628156e50dfed7da14619a4172dolc } 2732ead49f0d5873628156e50dfed7da14619a4172dolc } 2742ead49f0d5873628156e50dfed7da14619a4172dolc return NULL; 2752ead49f0d5873628156e50dfed7da14619a4172dolc} 2762ead49f0d5873628156e50dfed7da14619a4172dolc 27744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 27844d362409d5469aed47d19e7908d19bd194493aThomas Graf 27944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops rtnl_class_ops = { 28044d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_name = "route/class", 28144d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_hdrsize = sizeof(struct tcmsg), 28244d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msgtypes = { 28344d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_NEWTCLASS, NL_ACT_NEW, "new" }, 28444d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_DELTCLASS, NL_ACT_DEL, "del" }, 28544d362409d5469aed47d19e7908d19bd194493aThomas Graf { RTM_GETTCLASS, NL_ACT_GET, "get" }, 28644d362409d5469aed47d19e7908d19bd194493aThomas Graf END_OF_MSGTYPES_LIST, 28744d362409d5469aed47d19e7908d19bd194493aThomas Graf }, 28844d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_protocol = NETLINK_ROUTE, 28944d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_request_update = &class_request_update, 29044d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_msg_parser = &class_msg_parser, 29144d362409d5469aed47d19e7908d19bd194493aThomas Graf .co_obj_ops = &class_obj_ops, 29244d362409d5469aed47d19e7908d19bd194493aThomas Graf}; 29344d362409d5469aed47d19e7908d19bd194493aThomas Graf 29444d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __init class_init(void) 29544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 29644d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_register(&rtnl_class_ops); 29744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 29844d362409d5469aed47d19e7908d19bd194493aThomas Graf 29944d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic void __exit class_exit(void) 30044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 30144d362409d5469aed47d19e7908d19bd194493aThomas Graf nl_cache_mngt_unregister(&rtnl_class_ops); 30244d362409d5469aed47d19e7908d19bd194493aThomas Graf} 30344d362409d5469aed47d19e7908d19bd194493aThomas Graf 30444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 305