kernel: Add option to control DS field behavior

This commit is contained in:
Tobias Brunner
2018-08-29 11:36:04 +02:00
parent dc8b015d78
commit c993eaf9d1
9 changed files with 129 additions and 4 deletions
+15
View File
@@ -147,6 +147,11 @@ struct private_child_cfg_t {
* HW offload mode
*/
hw_offload_t hw_offload;
/**
* DS header field copy mode
*/
dscp_copy_t copy_dscp;
};
METHOD(child_cfg_t, get_name, char*,
@@ -487,6 +492,12 @@ METHOD(child_cfg_t, get_hw_offload, hw_offload_t,
return this->hw_offload;
}
METHOD(child_cfg_t, get_copy_dscp, dscp_copy_t,
private_child_cfg_t *this)
{
return this->copy_dscp;
}
METHOD(child_cfg_t, get_dpd_action, action_t,
private_child_cfg_t *this)
{
@@ -612,6 +623,8 @@ METHOD(child_cfg_t, equals, bool,
this->tfc == other->tfc &&
this->manual_prio == other->manual_prio &&
this->replay_window == other->replay_window &&
this->hw_offload == other->hw_offload &&
this->copy_dscp == other->copy_dscp &&
streq(this->updown, other->updown) &&
streq(this->interface, other->interface);
}
@@ -673,6 +686,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.get_ref = _get_ref,
.destroy = _destroy,
.get_hw_offload = _get_hw_offload,
.get_copy_dscp = _get_copy_dscp,
},
.name = strdup(name),
.options = data->options,
@@ -696,6 +710,7 @@ child_cfg_t *child_cfg_create(char *name, child_cfg_create_t *data)
.replay_window = lib->settings->get_int(lib->settings,
"%s.replay_window", DEFAULT_REPLAY_WINDOW, lib->ns),
.hw_offload = data->hw_offload,
.copy_dscp = data->copy_dscp,
);
return &this->public;
+9
View File
@@ -191,6 +191,13 @@ struct child_cfg_t {
*/
hw_offload_t (*get_hw_offload) (child_cfg_t *this);
/**
* Get the copy mode for the DS header field to use for the CHILD_SA.
*
* @return IP header copy mode
*/
dscp_copy_t (*get_copy_dscp) (child_cfg_t *this);
/**
* Action to take if CHILD_SA gets closed.
*
@@ -361,6 +368,8 @@ struct child_cfg_create_t {
char *updown;
/** HW offload mode */
hw_offload_t hw_offload;
/** How to handle the DS header field in tunnel mode */
dscp_copy_t copy_dscp;
};
/**
+2
View File
@@ -99,6 +99,8 @@ struct kernel_ipsec_add_sa_t {
bool copy_df;
/** TRUE to copy the ECN header field to/from the outer header */
bool copy_ecn;
/** Whether to copy the DSCP header field to/from the outer header */
dscp_copy_t copy_dscp;
/** TRUE if initiator of the exchange creating the SA */
bool initiator;
/** TRUE if this is an inbound SA */
@@ -1597,6 +1597,42 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
sa->flags |= XFRM_STATE_NOECN;
}
if (data->inbound)
{
switch (data->copy_dscp)
{
case DSCP_COPY_YES:
case DSCP_COPY_IN_ONLY:
sa->flags |= XFRM_STATE_DECAP_DSCP;
break;
default:
break;
}
}
else
{
switch (data->copy_dscp)
{
case DSCP_COPY_IN_ONLY:
case DSCP_COPY_NO:
{
uint32_t *xflags;
xflags = netlink_reserve(hdr, sizeof(request),
XFRMA_SA_EXTRA_FLAGS, sizeof(*xflags));
if (!xflags)
{
goto failed;
}
/* currently the only extra flag */
*xflags |= XFRM_SA_XFLAG_DONT_ENCAP_DSCP;
break;
}
default:
break;
}
}
switch (mode)
{
case MODE_TUNNEL:
+24
View File
@@ -536,6 +536,7 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " sha256_96 = %u", has_opt(OPT_SHA256_96));
DBG2(DBG_CFG, " copy_df = %u", !has_opt(OPT_NO_COPY_DF));
DBG2(DBG_CFG, " copy_ecn = %u", !has_opt(OPT_NO_COPY_ECN));
DBG2(DBG_CFG, " copy_dscp = %N", dscp_copy_names, cfg->copy_dscp);
}
/**
@@ -939,6 +940,28 @@ CALLBACK(parse_opt_copy_ecn, bool,
return parse_option(out, OPT_NO_COPY_ECN, v, FALSE);
}
/**
* Parse a dscp_copy_t
*/
CALLBACK(parse_copy_dscp, bool,
dscp_copy_t *out, chunk_t v)
{
enum_map_t map[] = {
{ "no", DSCP_COPY_NO },
{ "in", DSCP_COPY_IN_ONLY },
{ "out", DSCP_COPY_OUT_ONLY },
{ "yes", DSCP_COPY_YES },
};
int d;
if (parse_map(map, countof(map), &d, v))
{
*out = d;
return TRUE;
}
return FALSE;
}
/**
* Parse an action_t
*/
@@ -1623,6 +1646,7 @@ CALLBACK(child_kv, bool,
{ "sha256_96", parse_opt_sha256_96,&child->cfg.options },
{ "copy_df", parse_opt_copy_df, &child->cfg.options },
{ "copy_ecn", parse_opt_copy_ecn, &child->cfg.options },
{ "copy_dscp", parse_copy_dscp, &child->cfg.copy_dscp },
};
return parse_rules(rules, countof(rules), name, value,
+1
View File
@@ -893,6 +893,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
.esn = esn,
.copy_df = !this->config->has_option(this->config, OPT_NO_COPY_DF),
.copy_ecn = !this->config->has_option(this->config, OPT_NO_COPY_ECN),
.copy_dscp = this->config->get_copy_dscp(this->config),
.initiator = initiator,
.inbound = inbound,
.update = update,