1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #include <linux/kernel.h> 3 #include <linux/slab.h> 4 #include <net/flow_offload.h> 5 #include <net/pkt_cls.h> 6 7 struct flow_rule *flow_rule_alloc(unsigned int num_actions) 8 { 9 struct flow_rule *rule; 10 11 rule = kzalloc(struct_size(rule, action.entries, num_actions), 12 GFP_KERNEL); 13 if (!rule) 14 return NULL; 15 16 rule->action.num_entries = num_actions; 17 18 return rule; 19 } 20 EXPORT_SYMBOL(flow_rule_alloc); 21 22 #define FLOW_DISSECTOR_MATCH(__rule, __type, __out) \ 23 const struct flow_match *__m = &(__rule)->match; \ 24 struct flow_dissector *__d = (__m)->dissector; \ 25 \ 26 (__out)->key = skb_flow_dissector_target(__d, __type, (__m)->key); \ 27 (__out)->mask = skb_flow_dissector_target(__d, __type, (__m)->mask); \ 28 29 void flow_rule_match_meta(const struct flow_rule *rule, 30 struct flow_match_meta *out) 31 { 32 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_META, out); 33 } 34 EXPORT_SYMBOL(flow_rule_match_meta); 35 36 void flow_rule_match_basic(const struct flow_rule *rule, 37 struct flow_match_basic *out) 38 { 39 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_BASIC, out); 40 } 41 EXPORT_SYMBOL(flow_rule_match_basic); 42 43 void flow_rule_match_control(const struct flow_rule *rule, 44 struct flow_match_control *out) 45 { 46 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_CONTROL, out); 47 } 48 EXPORT_SYMBOL(flow_rule_match_control); 49 50 void flow_rule_match_eth_addrs(const struct flow_rule *rule, 51 struct flow_match_eth_addrs *out) 52 { 53 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS, out); 54 } 55 EXPORT_SYMBOL(flow_rule_match_eth_addrs); 56 57 void flow_rule_match_vlan(const struct flow_rule *rule, 58 struct flow_match_vlan *out) 59 { 60 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_VLAN, out); 61 } 62 EXPORT_SYMBOL(flow_rule_match_vlan); 63 64 void flow_rule_match_cvlan(const struct flow_rule *rule, 65 struct flow_match_vlan *out) 66 { 67 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_CVLAN, out); 68 } 69 EXPORT_SYMBOL(flow_rule_match_cvlan); 70 71 void flow_rule_match_ipv4_addrs(const struct flow_rule *rule, 72 struct flow_match_ipv4_addrs *out) 73 { 74 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS, out); 75 } 76 EXPORT_SYMBOL(flow_rule_match_ipv4_addrs); 77 78 void flow_rule_match_ipv6_addrs(const struct flow_rule *rule, 79 struct flow_match_ipv6_addrs *out) 80 { 81 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS, out); 82 } 83 EXPORT_SYMBOL(flow_rule_match_ipv6_addrs); 84 85 void flow_rule_match_ip(const struct flow_rule *rule, 86 struct flow_match_ip *out) 87 { 88 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IP, out); 89 } 90 EXPORT_SYMBOL(flow_rule_match_ip); 91 92 void flow_rule_match_ports(const struct flow_rule *rule, 93 struct flow_match_ports *out) 94 { 95 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_PORTS, out); 96 } 97 EXPORT_SYMBOL(flow_rule_match_ports); 98 99 void flow_rule_match_tcp(const struct flow_rule *rule, 100 struct flow_match_tcp *out) 101 { 102 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_TCP, out); 103 } 104 EXPORT_SYMBOL(flow_rule_match_tcp); 105 106 void flow_rule_match_icmp(const struct flow_rule *rule, 107 struct flow_match_icmp *out) 108 { 109 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ICMP, out); 110 } 111 EXPORT_SYMBOL(flow_rule_match_icmp); 112 113 void flow_rule_match_mpls(const struct flow_rule *rule, 114 struct flow_match_mpls *out) 115 { 116 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_MPLS, out); 117 } 118 EXPORT_SYMBOL(flow_rule_match_mpls); 119 120 void flow_rule_match_enc_control(const struct flow_rule *rule, 121 struct flow_match_control *out) 122 { 123 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL, out); 124 } 125 EXPORT_SYMBOL(flow_rule_match_enc_control); 126 127 void flow_rule_match_enc_ipv4_addrs(const struct flow_rule *rule, 128 struct flow_match_ipv4_addrs *out) 129 { 130 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, out); 131 } 132 EXPORT_SYMBOL(flow_rule_match_enc_ipv4_addrs); 133 134 void flow_rule_match_enc_ipv6_addrs(const struct flow_rule *rule, 135 struct flow_match_ipv6_addrs *out) 136 { 137 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, out); 138 } 139 EXPORT_SYMBOL(flow_rule_match_enc_ipv6_addrs); 140 141 void flow_rule_match_enc_ip(const struct flow_rule *rule, 142 struct flow_match_ip *out) 143 { 144 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IP, out); 145 } 146 EXPORT_SYMBOL(flow_rule_match_enc_ip); 147 148 void flow_rule_match_enc_ports(const struct flow_rule *rule, 149 struct flow_match_ports *out) 150 { 151 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_PORTS, out); 152 } 153 EXPORT_SYMBOL(flow_rule_match_enc_ports); 154 155 void flow_rule_match_enc_keyid(const struct flow_rule *rule, 156 struct flow_match_enc_keyid *out) 157 { 158 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_KEYID, out); 159 } 160 EXPORT_SYMBOL(flow_rule_match_enc_keyid); 161 162 void flow_rule_match_enc_opts(const struct flow_rule *rule, 163 struct flow_match_enc_opts *out) 164 { 165 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_OPTS, out); 166 } 167 EXPORT_SYMBOL(flow_rule_match_enc_opts); 168 169 int flow_block_cb_setup_simple(struct flow_block_offload *f, 170 struct list_head *driver_block_list, 171 tc_setup_cb_t *cb, void *cb_ident, void *cb_priv, 172 bool ingress_only) 173 { 174 if (ingress_only && 175 f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) 176 return -EOPNOTSUPP; 177 178 f->driver_block_list = driver_block_list; 179 180 switch (f->command) { 181 case TC_BLOCK_BIND: 182 return tcf_block_cb_register(f->block, cb, cb_ident, cb_priv, 183 f->extack); 184 case TC_BLOCK_UNBIND: 185 tcf_block_cb_unregister(f->block, cb, cb_ident); 186 return 0; 187 default: 188 return -EOPNOTSUPP; 189 } 190 } 191 EXPORT_SYMBOL(flow_block_cb_setup_simple); 192