Skip to content

Commit

Permalink
datapath-windows: Add support for 'OVS_KEY_ATTR_ENCAP' key attribute.
Browse files Browse the repository at this point in the history
Add a new structure in l2 header to accomodate vlan header,
based of commit "d7efce7beff25052bd9083419200e1a47f0d6066
datapath: 802.1AD Flow handling, actions, vlan parsing, netlink attributes"

Also reset vlan header in flow key, after deleting vlan tag from nbl

With this change a sample vlan flow would look like,
eth(src=0a:ea:8a:24:03:86,dst=0a:cd:fa:4d:15:5c),in_port(3),eth_type(0x8100),
vlan(vid=2239,pcp=0),encap(eth_type(0x0800),ipv4(src=13.12.11.149,dst=13.12.11.107,
proto=1,tos=0,ttl=128,frag=no),icmp(type=8,code=0))

Signed-off-by: Anand Kumar <[email protected]>
Acked-by: Alin Gabriel Serdean <[email protected]>
Signed-off-by: Alin Gabriel Serdean <[email protected]>
  • Loading branch information
Anandkumar26 authored and aserdean committed Jan 28, 2019
1 parent 9da3207 commit c891534
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 16 deletions.
3 changes: 3 additions & 0 deletions datapath-windows/ovsext/Actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -2057,6 +2057,9 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
goto dropit;
}
}
/* Reset vlan header info in flowkey. */
key->l2.vlanKey.vlanTci = 0;
key->l2.vlanKey.vlanTpid = 0;
break;
}

Expand Down
12 changes: 9 additions & 3 deletions datapath-windows/ovsext/DpInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ typedef struct Icmp6Key {
struct in6_addr ndTarget; /* IPv6 neighbor discovery (ND) target. */
} Icmp6Key; /* Size of 72 byte. */

typedef struct VlanKey {
ovs_be16 vlanTci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
ovs_be16 vlanTpid; /* Vlan type. Generally 802.1q or 802.1ad.*/
} VlanKey;

typedef struct L2Key {
uint32_t inPort; /* Port number of input port. */
union {
Expand All @@ -123,9 +128,10 @@ typedef struct L2Key {
};
uint8_t dlSrc[6]; /* Ethernet source address. */
uint8_t dlDst[6]; /* Ethernet destination address. */
ovs_be16 vlanTci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
ovs_be16 dlType; /* Ethernet frame type. */
} L2Key; /* Size of 24 byte. */
struct VlanKey vlanKey; /* VLAN header. */
uint16_t pad[3]; /* Padding 6 bytes. */
} L2Key; /* Size of 32 byte. */

/* Number of packet attributes required to store OVS tunnel key. */
#define NUM_PKT_ATTR_REQUIRED 35
Expand Down Expand Up @@ -182,7 +188,7 @@ typedef struct MplsKey {

typedef __declspec(align(8)) struct OvsFlowKey {
OvsIPv4TunnelKey tunKey; /* 280 bytes */
L2Key l2; /* 24 bytes */
L2Key l2; /* 32 bytes */
union {
/* These headers are mutually exclusive. */
IpKey ipKey; /* size 16 */
Expand Down
126 changes: 113 additions & 13 deletions datapath-windows/ovsext/Flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const NL_POLICY nlFlowKeyPolicy[] = {
[OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
.maxLen = 4, .optional = TRUE},
[OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4,
.maxLen = 4, .optional = FALSE},
.maxLen = 4, .optional = TRUE},
[OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
.minLen = sizeof(struct ovs_key_ethernet),
.maxLen = sizeof(struct ovs_key_ethernet),
Expand Down Expand Up @@ -457,13 +457,15 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
NL_BUFFER nlBuf;
PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX];
PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX];
PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX];

NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
usrParamsCtx->outputLength);
RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput));
RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
UINT32 keyAttrOffset = 0;
UINT32 tunnelKeyAttrOffset = 0;
UINT32 encapOffset = 0;
BOOLEAN ok;
NL_ERROR nlError = NL_ERROR_SUCCESS;

Expand Down Expand Up @@ -503,6 +505,23 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
goto done;
}

if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {
encapOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_ENCAP])
- (PCHAR)nlMsgHdr);

if ((NlAttrParseNested(nlMsgHdr, encapOffset,
NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),
nlFlowKeyPolicy,
ARRAY_SIZE(nlFlowKeyPolicy),
encapAttrs, ARRAY_SIZE(encapAttrs)))
!= TRUE) {
OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p",
nlMsgHdr);
rc = STATUS_INVALID_PARAMETER;
goto done;
}
}

if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
tunnelKeyAttrOffset = (UINT32)((PCHAR)
(keyAttrs[OVS_KEY_ATTR_TUNNEL])
Expand All @@ -524,6 +543,12 @@ _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,

_MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
&(getInput.key));
ASSERT(keyAttrs[OVS_KEY_ATTR_IN_PORT]);

if (encapOffset) {
_MapKeyAttrToFlowPut(encapAttrs, tunnelAttrs,
&(getInput.key));
}

getInput.dpNo = ovsHdr->dp_ifindex;
getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS;
Expand Down Expand Up @@ -855,7 +880,7 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
{
NTSTATUS rc = STATUS_SUCCESS;
struct ovs_key_ethernet ethKey;
UINT32 offset = 0;
UINT32 offset = 0, encap_offset = 0;

offset = NlMsgStartNested(nlBuf, keyType);
if (!offset) {
Expand Down Expand Up @@ -924,17 +949,34 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
}

if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
flowKey->l2.dlType)) {
flowKey->l2.vlanKey.vlanTci == 0 ? flowKey->l2.dlType :
flowKey->l2.vlanKey.vlanTpid)) {
rc = STATUS_UNSUCCESSFUL;
goto done;
}

if (flowKey->l2.vlanTci) {
if (flowKey->l2.vlanKey.vlanTci ||
flowKey->l2.dlType == ETH_TYPE_802_1PQ) {
if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN,
flowKey->l2.vlanTci)) {
flowKey->l2.vlanKey.vlanTci)) {
rc = STATUS_UNSUCCESSFUL;
goto done;
}

/* Add encap attributes. */
encap_offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_ENCAP);
if (!encap_offset) {
/* Starting the nested attribute failed. */
rc = STATUS_UNSUCCESSFUL;
goto done;
}

/* Add packet Ethernet Type*/
if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
flowKey->l2.dlType)) {
rc = STATUS_UNSUCCESSFUL;
goto encap;
}
}

/* ==== L3 + L4 ==== */
Expand Down Expand Up @@ -982,6 +1024,10 @@ MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
goto done;
}
}
encap:
if (encap_offset) {
NlMsgEndNested(nlBuf, encap_offset);
}

done:
NlMsgEndNested(nlBuf, offset);
Expand Down Expand Up @@ -1336,9 +1382,11 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,

UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
UINT32 tunnelKeyAttrOffset;
UINT32 encapOffset = 0;

PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL};
PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL};
PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX] = { NULL };

/* Get flow keys attributes */
if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
Expand All @@ -1351,6 +1399,23 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,
goto done;
}

if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {
encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP])
- (PCHAR)nlMsgHdr);

if ((NlAttrParseNested(nlMsgHdr, encapOffset,
NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),
nlFlowKeyPolicy,
ARRAY_SIZE(nlFlowKeyPolicy),
encapAttrs, ARRAY_SIZE(encapAttrs)))
!= TRUE) {
OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p",
nlMsgHdr);
rc = STATUS_INVALID_PARAMETER;
goto done;
}
}

if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) {
tunnelKeyAttrOffset = (UINT32)((PCHAR)
(keyAttrs[OVS_KEY_ATTR_TUNNEL])
Expand All @@ -1372,6 +1437,12 @@ _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr,

_MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs,
&(mappedFlow->key));
ASSERT(keyAttrs[OVS_KEY_ATTR_IN_PORT]);

if (encapOffset) {
_MapKeyAttrToFlowPut(encapAttrs, tunnelAttrs,
&(mappedFlow->key));
}

/* Map the action */
if (actionAttr) {
Expand Down Expand Up @@ -1469,7 +1540,9 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
}

/* ===== L2 headers ===== */
destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
if (keyAttrs[OVS_KEY_ATTR_IN_PORT]) {
destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
}

if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
const struct ovs_key_ethernet *eth_key;
Expand All @@ -1488,7 +1561,11 @@ _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs,
}

if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
destKey->l2.vlanKey.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
if (destKey->l2.vlanKey.vlanTci != 0) {
/* set TPID to dlType. */
destKey->l2.vlanKey.vlanTpid = destKey->l2.dlType;
}
}

/* ==== L3 + L4. ==== */
Expand Down Expand Up @@ -2267,17 +2344,20 @@ OvsExtractFlow(const NET_BUFFER_LIST *packet,
if (vlanTagValue) {
PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag =
(PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue;
flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
(vlanTag->TagHeader.UserPriority << 13));
flow->l2.vlanKey.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI |
(vlanTag->TagHeader.UserPriority << 13));
flow->l2.vlanKey.vlanTpid = htons(ETH_TYPE_802_1PQ);
} else {
if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) {
Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)&eth->dix.typeNBO;
flow->l2.vlanTci = ((UINT16)tag->priority << 13) |
OVSWIN_VLAN_CFI |
((UINT16)tag->vidHi << 8) | tag->vidLo;
flow->l2.vlanKey.vlanTci = ((UINT16)tag->priority << 13) |
OVSWIN_VLAN_CFI | ((UINT16)tag->vidHi << 8) | tag->vidLo;
flow->l2.vlanKey.vlanTpid = htons(ETH_TYPE_802_1PQ);
offset = sizeof (Eth_802_1pq_Tag);
} else {
flow->l2.vlanTci = 0;
/* Initialize vlan key to 0 for non vlan packets. */
flow->l2.vlanKey.vlanTci = 0;
flow->l2.vlanKey.vlanTpid = 0;
}
/*
* XXX Please note after this point, src mac and dst mac should
Expand Down Expand Up @@ -3095,7 +3175,9 @@ OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);

UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr);
UINT32 encapOffset = 0;
PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = { NULL };
PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX] = { NULL };

/* Get flow keys attributes */
if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr),
Expand All @@ -3108,6 +3190,24 @@ OvsProbeSupportedFeature(POVS_MESSAGE msgIn,
goto done;
}

if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {
encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP])
- (PCHAR)nlMsgHdr);

/* Get tunnel keys attributes */
if ((NlAttrParseNested(nlMsgHdr, encapOffset,
NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),
nlFlowKeyPolicy,
ARRAY_SIZE(nlFlowKeyPolicy),
encapAttrs, ARRAY_SIZE(encapAttrs)))
!= TRUE) {
OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p",
nlMsgHdr);
status = STATUS_INVALID_PARAMETER;
goto done;
}
}

if (keyAttrs[OVS_KEY_ATTR_MPLS] &&
keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
ovs_be16 ethType = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_ETHERTYPE]);
Expand Down
19 changes: 19 additions & 0 deletions datapath-windows/ovsext/User.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,25 @@ OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
goto done;
}

if (keyAttrs[OVS_KEY_ATTR_ENCAP]) {
UINT32 encapOffset = 0;
PNL_ATTR encapAttrs[__OVS_KEY_ATTR_MAX];
encapOffset = (UINT32)((PCHAR)(keyAttrs[OVS_KEY_ATTR_ENCAP])
- (PCHAR)nlMsgHdr);

if ((NlAttrParseNested(nlMsgHdr, encapOffset,
NlAttrLen(keyAttrs[OVS_KEY_ATTR_ENCAP]),
nlFlowKeyPolicy,
nlFlowKeyPolicyLen,
encapAttrs, ARRAY_SIZE(encapAttrs)))
!= TRUE) {
OVS_LOG_ERROR("Encap Key Attr Parsing failed for msg: %p",
nlMsgHdr);
status = STATUS_UNSUCCESSFUL;
goto done;
}
}

execute.dpNo = ovsHdr->dp_ifindex;

_MapNlAttrToOvsPktExec(nlMsgHdr, nlAttrs, keyAttrs, &execute);
Expand Down

0 comments on commit c891534

Please sign in to comment.