Attaches a redirect action to the libnl filter (rtnl_cls).
| 98 | |
| 99 | // Attaches a redirect action to the libnl filter (rtnl_cls). |
| 100 | inline Try<Nothing> attach( |
| 101 | const Netlink<struct rtnl_cls>& cls, |
| 102 | const action::Redirect& redirect) |
| 103 | { |
| 104 | Result<Netlink<struct rtnl_link>> link = |
| 105 | link::internal::get(redirect.link); |
| 106 | |
| 107 | if (link.isError()) { |
| 108 | return Error(link.error()); |
| 109 | } else if (link.isNone()) { |
| 110 | return Error("Link '" + redirect.link + "' is not found"); |
| 111 | } |
| 112 | |
| 113 | Netlink<struct rtnl_act> act(rtnl_act_alloc()); |
| 114 | if (act.get() == nullptr) { |
| 115 | return Error("Failed to allocate a libnl action (rtnl_act)"); |
| 116 | } |
| 117 | |
| 118 | // Set the kind of the action to 'mirred'. The kind 'mirred' stands |
| 119 | // for mirror or redirect actions. |
| 120 | int error = rtnl_tc_set_kind(TC_CAST(act.get()), "mirred"); |
| 121 | if (error != 0) { |
| 122 | return Error( |
| 123 | "Failed to set the kind of the action: " + |
| 124 | std::string(nl_geterror(error))); |
| 125 | } |
| 126 | |
| 127 | rtnl_mirred_set_ifindex(act.get(), rtnl_link_get_ifindex(link->get())); |
| 128 | rtnl_mirred_set_action(act.get(), TCA_EGRESS_REDIR); |
| 129 | rtnl_mirred_set_policy(act.get(), TC_ACT_STOLEN); |
| 130 | |
| 131 | const std::string kind = rtnl_tc_get_kind(TC_CAST(cls.get())); |
| 132 | if (kind == "basic") { |
| 133 | error = rtnl_basic_add_action(cls.get(), act.get()); |
| 134 | if (error != 0) { |
| 135 | return Error(std::string(nl_geterror(error))); |
| 136 | } |
| 137 | } else if (kind == "u32") { |
| 138 | error = rtnl_u32_add_action(cls.get(), act.get()); |
| 139 | if (error != 0) { |
| 140 | return Error(std::string(nl_geterror(error))); |
| 141 | } |
| 142 | |
| 143 | // Automatically set the 'terminal' flag for u32 filters if a |
| 144 | // redirect action is attached. |
| 145 | error = rtnl_u32_set_cls_terminal(cls.get()); |
| 146 | if (error != 0) { |
| 147 | return Error( |
| 148 | "Failed to set the terminal flag: " + |
| 149 | std::string(nl_geterror(error))); |
| 150 | } |
| 151 | } else { |
| 152 | return Error("Unsupported classifier kind: " + kind); |
| 153 | } |
| 154 | |
| 155 | return Nothing(); |
| 156 | } |
| 157 |