| 164 | const std::string kind = rtnl_tc_get_kind(TC_CAST(cls.get())); |
| 165 | |
| 166 | foreach (const std::string& _link, mirror.links) { |
| 167 | Result<Netlink<struct rtnl_link>> link = link::internal::get(_link); |
| 168 | if (link.isError()) { |
| 169 | return Error(link.error()); |
| 170 | } else if (link.isNone()) { |
| 171 | return Error("Link '" + _link + "' is not found"); |
| 172 | } |
| 173 | |
| 174 | Netlink<struct rtnl_act> act(rtnl_act_alloc()); |
| 175 | if (act.get() == nullptr) { |
| 176 | return Error("Failed to allocate a libnl action (rtnl_act)"); |
| 177 | } |
| 178 | |
| 179 | int error = rtnl_tc_set_kind(TC_CAST(act.get()), "mirred"); |
| 180 | if (error != 0) { |
| 181 | return Error( |
| 182 | "Failed to set the kind of the action: " + |
| 183 | std::string(nl_geterror(error))); |
| 184 | } |
| 185 | |
| 186 | rtnl_mirred_set_ifindex(act.get(), rtnl_link_get_ifindex(link->get())); |
| 187 | rtnl_mirred_set_action(act.get(), TCA_EGRESS_MIRROR); |
| 188 | rtnl_mirred_set_policy(act.get(), TC_ACT_PIPE); |
| 189 | |
| 190 | if (kind == "basic") { |
| 191 | error = rtnl_basic_add_action(cls.get(), act.get()); |
| 192 | if (error != 0) { |
| 193 | return Error(std::string(nl_geterror(error))); |
| 194 | } |
| 195 | } else if (kind == "u32") { |
| 196 | error = rtnl_u32_add_action(cls.get(), act.get()); |
| 197 | if (error != 0) { |
| 198 | return Error(std::string(nl_geterror(error))); |
| 199 | } |
| 200 | } else { |
| 201 | return Error("Unsupported classifier kind: " + kind); |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | // Automatically set the 'terminal' flag for u32 filters if a mirror |
| 206 | // action is attached. |