On 9 November 2016 at 16:34, Sairam Venugopal <[email protected]> wrote:

> Add support for tracking ICMP code and Type in the Hyper-V Conntrack
> module. This code is similar to the userspace connection tracker.
>
> Signed-off-by: Sairam Venugopal <[email protected]>
>
Thanks, applied.


> ---
>  datapath-windows/ovsext/Conntrack-icmp.c  | 84
> +++++++++++++++++++++++++++++++
>  datapath-windows/ovsext/Conntrack-other.c | 15 ++----
>  datapath-windows/ovsext/Conntrack-tcp.c   | 25 ++++-----
>  datapath-windows/ovsext/Conntrack.c       | 73
> ++++++++++++++++++++++++---
>  datapath-windows/ovsext/Conntrack.h       | 24 ++++++++-
>  datapath-windows/ovsext/ovsext.vcxproj    |  1 +
>  6 files changed, 190 insertions(+), 32 deletions(-)
>  create mode 100644 datapath-windows/ovsext/Conntrack-icmp.c
>
> diff --git a/datapath-windows/ovsext/Conntrack-icmp.c
> b/datapath-windows/ovsext/Conntrack-icmp.c
> new file mode 100644
> index 0000000..7db8e7d
> --- /dev/null
> +++ b/datapath-windows/ovsext/Conntrack-icmp.c
> @@ -0,0 +1,84 @@
> +/*
> + * Copyright (c) 2016 VMware, Inc.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at:
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#include "NetProto.h"
> +#include "Conntrack.h"
> +#include <stddef.h>
> +
> +enum icmp_state {
> +    ICMPS_FIRST,
> +    ICMPS_REPLY,
> +};
> +
> +struct conn_icmp {
> +    struct OVS_CT_ENTRY up;
> +    enum icmp_state state;
> +};
> +
> +static const enum ct_timeout icmp_timeouts[] = {
> +    [ICMPS_FIRST] = 60 * CT_INTERVAL_SEC,
> +    [ICMPS_REPLY] = 30 * CT_INTERVAL_SEC,
> +};
> +
> +static __inline struct conn_icmp *
> +OvsCastConntrackEntryToIcmpEntry(OVS_CT_ENTRY* conn)
> +{
> +    return CONTAINER_OF(conn, struct conn_icmp, up);
> +}
> +
> +enum CT_UPDATE_RES
> +OvsConntrackUpdateIcmpEntry(OVS_CT_ENTRY* conn_,
> +                            BOOLEAN reply,
> +                            UINT64 now)
> +{
> +    struct conn_icmp *conn = OvsCastConntrackEntryToIcmpEntry(conn_);
> +
> +    if (reply && conn->state != ICMPS_REPLY) {
> +        conn->state = ICMPS_REPLY;
> +    }
> +
> +    OvsConntrackUpdateExpiration(&conn->up, now,
> +                                 icmp_timeouts[conn->state]);
> +
> +    return CT_UPDATE_VALID;
> +}
> +
> +BOOLEAN
> +OvsConntrackValidateIcmpPacket(const ICMPHdr *icmp)
> +{
> +    return icmp->type == ICMP4_ECHO_REQUEST
> +           || icmp->type == ICMP4_INFO_REQUEST
> +           || icmp->type == ICMP4_TIMESTAMP_REQUEST;
> +}
> +
> +OVS_CT_ENTRY *
> +OvsConntrackCreateIcmpEntry(UINT64 now)
> +{
> +    struct conn_icmp *conn;
> +
> +    conn = OvsAllocateMemoryWithTag(sizeof(struct conn_icmp),
> +                                    OVS_CT_POOL_TAG);
> +    if (!conn) {
> +        return NULL;
> +    }
> +
> +    conn->state = ICMPS_FIRST;
> +
> +    OvsConntrackUpdateExpiration(&conn->up, now,
> +                                 icmp_timeouts[conn->state]);
> +
> +    return &conn->up;
> +}
> diff --git a/datapath-windows/ovsext/Conntrack-other.c
> b/datapath-windows/ovsext/Conntrack-other.c
> index b853020..6c68ba8 100644
> --- a/datapath-windows/ovsext/Conntrack-other.c
> +++ b/datapath-windows/ovsext/Conntrack-other.c
> @@ -41,14 +41,7 @@ OvsCastConntrackEntryToOtherEntry(OVS_CT_ENTRY *conn)
>      return CONTAINER_OF(conn, struct conn_other, up);
>  }
>
> -static __inline VOID
> -OvsConntrackUpdateExpiration(struct conn_other *conn, long long now)
> -{
> -    ASSERT(conn);
> -    conn->up.expiration = now + other_timeouts[conn->state];
> -}
> -
> -enum ct_update_res
> +enum CT_UPDATE_RES
>  OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
>                               BOOLEAN reply,
>                               UINT64 now)
> @@ -62,7 +55,8 @@ OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
>          conn->state = OTHERS_MULTIPLE;
>      }
>
> -    OvsConntrackUpdateExpiration(conn, now);
> +    OvsConntrackUpdateExpiration(&conn->up, now,
> +                                 other_timeouts[conn->state]);
>
>      return CT_UPDATE_VALID;
>  }
> @@ -78,6 +72,7 @@ OvsConntrackCreateOtherEntry(UINT64 now)
>      }
>      conn->up = (OVS_CT_ENTRY) {0};
>      conn->state = OTHERS_FIRST;
> -    OvsConntrackUpdateExpiration(conn, now);
> +    OvsConntrackUpdateExpiration(&conn->up, now,
> +                                 other_timeouts[conn->state]);
>      return &conn->up;
>  }
> diff --git a/datapath-windows/ovsext/Conntrack-tcp.c
> b/datapath-windows/ovsext/Conntrack-tcp.c
> index 6adf490..c7fcfa8 100644
> --- a/datapath-windows/ovsext/Conntrack-tcp.c
> +++ b/datapath-windows/ovsext/Conntrack-tcp.c
> @@ -199,14 +199,6 @@ OvsGetTcpPayloadLength(PNET_BUFFER_LIST nbl)
>                          - (sizeof * tcp);
>  }
>
> -static __inline void
> -OvsConntrackUpdateExpiration(struct conn_tcp *conn,
> -                             long long now,
> -                             long long interval)
> -{
> -    conn->up.expiration = now + interval;
> -}
> -
>  static __inline struct conn_tcp*
>  OvsCastConntrackEntryToTcpEntry(OVS_CT_ENTRY* conn)
>  {
> @@ -383,18 +375,23 @@ OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,
>
>          if (src->state >= CT_DPIF_TCPS_FIN_WAIT_2
>              && dst->state >= CT_DPIF_TCPS_FIN_WAIT_2) {
> -            OvsConntrackUpdateExpiration(conn, now, 30 *
> CT_INTERVAL_SEC);
> +            OvsConntrackUpdateExpiration(&conn->up, now,
> +                                         30 * CT_INTERVAL_SEC);
>          } else if (src->state >= CT_DPIF_TCPS_CLOSING
>                     && dst->state >= CT_DPIF_TCPS_CLOSING) {
> -            OvsConntrackUpdateExpiration(conn, now, 45 *
> CT_INTERVAL_SEC);
> +            OvsConntrackUpdateExpiration(&conn->up, now,
> +                                         45 * CT_INTERVAL_SEC);
>          } else if (src->state < CT_DPIF_TCPS_ESTABLISHED
>                     || dst->state < CT_DPIF_TCPS_ESTABLISHED) {
> -            OvsConntrackUpdateExpiration(conn, now, 30 *
> CT_INTERVAL_SEC);
> +            OvsConntrackUpdateExpiration(&conn->up, now,
> +                                         30 * CT_INTERVAL_SEC);
>          } else if (src->state >= CT_DPIF_TCPS_CLOSING
>                     || dst->state >= CT_DPIF_TCPS_CLOSING) {
> -            OvsConntrackUpdateExpiration(conn, now, 15 * 60 *
> CT_INTERVAL_SEC);
> +            OvsConntrackUpdateExpiration(&conn->up, now,
> +                                         15 * 60 * CT_INTERVAL_SEC);
>          } else {
> -            OvsConntrackUpdateExpiration(conn, now, 24 * 60 * 60 *
> CT_INTERVAL_SEC);
> +            OvsConntrackUpdateExpiration(&conn->up, now,
> +                                         24 * 60 * 60 * CT_INTERVAL_SEC);
>          }
>      } else if ((dst->state < CT_DPIF_TCPS_SYN_SENT
>                  || dst->state >= CT_DPIF_TCPS_FIN_WAIT_2
> @@ -518,7 +515,7 @@ OvsConntrackCreateTcpEntry(const TCPHdr *tcp,
>      src->state = CT_DPIF_TCPS_SYN_SENT;
>      dst->state = CT_DPIF_TCPS_CLOSED;
>
> -    OvsConntrackUpdateExpiration(newconn, now, CT_ENTRY_TIMEOUT);
> +    OvsConntrackUpdateExpiration(&newconn->up, now, CT_ENTRY_TIMEOUT);
>
>      return &newconn->up;
>  }
> diff --git a/datapath-windows/ovsext/Conntrack.c
> b/datapath-windows/ovsext/Conntrack.c
> index 74fb38c..b0846f6 100644
> --- a/datapath-windows/ovsext/Conntrack.c
> +++ b/datapath-windows/ovsext/Conntrack.c
> @@ -211,7 +211,28 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl,
>              return entry;
>          }
>          case IPPROTO_ICMP:
> +        {
> +            ICMPHdr storage;
> +            const ICMPHdr *icmp;
> +            icmp = OvsGetIcmp(curNbl, l4Offset, &storage);
> +            if (!OvsConntrackValidateIcmpPacket(icmp)) {
> +                goto invalid;
> +            }
> +
> +            state |= OVS_CS_F_NEW;
> +            if (commit) {
> +                entry = OvsConntrackCreateIcmpEntry(currentTime);
> +                if (!entry) {
> +                    return NULL;
> +                }
> +                OvsCtAddEntry(entry, ctx, currentTime);
> +            }
> +
> +            OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL);
> +            return entry;
> +        }
>          case IPPROTO_UDP:
> +        {
>              state |= OVS_CS_F_NEW;
>              if (commit) {
>                  entry = OvsConntrackCreateOtherEntry(currentTime);
> @@ -223,6 +244,7 @@ OvsCtEntryCreate(PNET_BUFFER_LIST curNbl,
>
>              OvsCtUpdateFlowKey(key, state, ctx->key.zone, 0, NULL);
>              return entry;
> +        }
>          default:
>              goto invalid;
>      }
> @@ -254,6 +276,7 @@ OvsCtUpdateEntry(OVS_CT_ENTRY* entry,
>              return OvsConntrackUpdateTcpEntry(entry, tcp, nbl, reply,
> now);
>          }
>          case IPPROTO_ICMP:
> +            return OvsConntrackUpdateIcmpEntry(entry, reply, now);
>          case IPPROTO_UDP:
>              return OvsConntrackUpdateOtherEntry(entry, reply, now);
>          default:
> @@ -338,8 +361,7 @@ OvsCtLookup(OvsConntrackKeyLookupCtx *ctx)
>      BOOLEAN reply = FALSE;
>      POVS_CT_ENTRY found = NULL;
>
> -    if (!ctTotalEntries)
> -    {
> +    if (!ctTotalEntries) {
>          return found;
>      }
>
> @@ -384,6 +406,27 @@ OvsExtractLookupCtxHash(OvsConntrackKeyLookupCtx
> *ctx)
>                           hash);
>  }
>
> +static UINT8
> +OvsReverseIcmpType(UINT8 type)
> +{
> +    switch (type) {
> +    case ICMP4_ECHO_REQUEST:
> +        return ICMP4_ECHO_REPLY;
> +    case ICMP4_ECHO_REPLY:
> +        return ICMP4_ECHO_REQUEST;
> +    case ICMP4_TIMESTAMP_REQUEST:
> +        return ICMP4_TIMESTAMP_REPLY;
> +    case ICMP4_TIMESTAMP_REPLY:
> +        return ICMP4_TIMESTAMP_REQUEST;
> +    case ICMP4_INFO_REQUEST:
> +        return ICMP4_INFO_REPLY;
> +    case ICMP4_INFO_REPLY:
> +        return ICMP4_INFO_REQUEST;
> +    default:
> +        return 0;
> +    }
> +}
> +
>  static __inline NDIS_STATUS
>  OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
>                      UINT16 zone,
> @@ -408,16 +451,31 @@ OvsCtSetupLookupCtx(OvsFlowKey *flowKey,
>              const ICMPHdr *icmp;
>              icmp = OvsGetIcmp(curNbl, l4Offset, &icmpStorage);
>              ASSERT(icmp);
> -            ctx->key.src.port = ctx->key.dst.port = icmp->fields.echo.id;
>
>              /* Related bit is set when ICMP has an error */
>              /* XXX parse out the appropriate src and dst from inner pkt */
>              switch (icmp->type) {
> +               case ICMP4_ECHO_REQUEST:
> +               case ICMP4_ECHO_REPLY:
> +               case ICMP4_TIMESTAMP_REQUEST:
> +               case ICMP4_TIMESTAMP_REPLY:
> +               case ICMP4_INFO_REQUEST:
> +               case ICMP4_INFO_REPLY:
> +                   if (icmp->code != 0) {
> +                       return NDIS_STATUS_INVALID_PACKET;
> +                   }
> +                   /* Separate ICMP connection: identified using id */
> +                   ctx->key.dst.icmp_id = icmp->fields.echo.id;
> +                   ctx->key.src.icmp_id = icmp->fields.echo.id;
> +                   ctx->key.src.icmp_type = icmp->type;
> +                   ctx->key.dst.icmp_type = OvsReverseIcmpType(icmp->type)
> ;
> +                   break;
>                 case ICMP4_DEST_UNREACH:
>                 case ICMP4_TIME_EXCEEDED:
>                 case ICMP4_PARAM_PROB:
>                 case ICMP4_SOURCE_QUENCH:
>                 case ICMP4_REDIRECT: {
> +                   /* XXX Handle inner packet */
>                     ctx->related = TRUE;
>                     break;
>                 }
> @@ -830,15 +888,18 @@ MapProtoTupleToNl(PNL_BUFFER nlBuf, OVS_CT_KEY *key)
>          || key->dl_type == ntohs(ETH_TYPE_IPV6)) {
>          /* ICMP and ICMPv6 Type, Code and ID are currently not tracked */
>          if (key->nw_proto == IPPROTO_ICMP) {
> -            if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMP_ID, 0)) {
> +            if (!NlMsgPutTailU16(nlBuf, CTA_PROTO_ICMP_ID,
> +                                 htons(key->src.icmp_id))) {
>                  status = NDIS_STATUS_FAILURE;
>                  goto done;
>              }
> -            if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_TYPE, 0)) {
> +            if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_TYPE,
> +                                key->src.icmp_type)) {
>                  status = NDIS_STATUS_FAILURE;
>                  goto done;
>              }
> -            if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_CODE, 0)) {
> +            if (!NlMsgPutTailU8(nlBuf, CTA_PROTO_ICMP_CODE,
> +                                key->src.icmp_code)) {
>                  status = NDIS_STATUS_FAILURE;
>                  goto done;
>              }
> diff --git a/datapath-windows/ovsext/Conntrack.h
> b/datapath-windows/ovsext/Conntrack.h
> index 4995ff4..270e2dd 100644
> --- a/datapath-windows/ovsext/Conntrack.h
> +++ b/datapath-windows/ovsext/Conntrack.h
> @@ -31,7 +31,14 @@ struct ct_addr {
>
>  struct ct_endpoint {
>      struct ct_addr addr;
> -    ovs_be16 port;
> +    union {
> +        ovs_be16 port;
> +        struct {
> +            ovs_be16 icmp_id;
> +            uint8_t icmp_type;
> +            uint8_t icmp_code;
> +        };
> +    };
>      UINT16 pad;
>  };
>
> @@ -94,6 +101,14 @@ typedef struct OvsConntrackKeyLookupCtx {
>          ((STRUCT *) (void *) ((char *) (POINTER) - \
>           offsetof (STRUCT, MEMBER)))
>
> +static __inline void
> +OvsConntrackUpdateExpiration(OVS_CT_ENTRY *ctEntry,
> +                             long long now,
> +                             long long interval)
> +{
> +    ctEntry->expiration = now + interval;
> +}
> +
>  VOID OvsCleanupConntrack(VOID);
>  NTSTATUS OvsInitConntrack(POVS_SWITCH_CONTEXT context);
>
> @@ -102,20 +117,25 @@ NDIS_STATUS OvsExecuteConntrackAction(PNET_BUFFER_LIST
> curNbl,
>                                        OvsFlowKey *key,
>                                        const PNL_ATTR a);
>  BOOLEAN OvsConntrackValidateTcpPacket(const TCPHdr *tcp);
> +BOOLEAN OvsConntrackValidateIcmpPacket(const ICMPHdr *icmp);
>  OVS_CT_ENTRY * OvsConntrackCreateTcpEntry(const TCPHdr *tcp,
>                                            PNET_BUFFER_LIST nbl,
>                                            UINT64 now);
>  NDIS_STATUS OvsCtMapTcpProtoInfoToNl(PNL_BUFFER nlBuf,
>                                       OVS_CT_ENTRY *conn_);
>  OVS_CT_ENTRY * OvsConntrackCreateOtherEntry(UINT64 now);
> +OVS_CT_ENTRY * OvsConntrackCreateIcmpEntry(UINT64 now);
>  enum CT_UPDATE_RES OvsConntrackUpdateTcpEntry(OVS_CT_ENTRY* conn_,
>                                                const TCPHdr *tcp,
>                                                PNET_BUFFER_LIST nbl,
>                                                BOOLEAN reply,
>                                                UINT64 now);
> -enum ct_update_res OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
> +enum CT_UPDATE_RES OvsConntrackUpdateOtherEntry(OVS_CT_ENTRY *conn_,
>                                                  BOOLEAN reply,
>                                                  UINT64 now);
> +enum CT_UPDATE_RES OvsConntrackUpdateIcmpEntry(OVS_CT_ENTRY* conn_,
> +                                               BOOLEAN reply,
> +                                               UINT64 now);
>  NTSTATUS
>  OvsCreateNlMsgFromCtEntry(POVS_CT_ENTRY entry,
>                            PVOID outBuffer,
> diff --git a/datapath-windows/ovsext/ovsext.vcxproj
> b/datapath-windows/ovsext/ovsext.vcxproj
> index a00deb0..77530fd 100644
> --- a/datapath-windows/ovsext/ovsext.vcxproj
> +++ b/datapath-windows/ovsext/ovsext.vcxproj
> @@ -178,6 +178,7 @@
>    <ItemGroup>
>      <ClCompile Include="Actions.c" />
>      <ClCompile Include="BufferMgmt.c" />
> +    <ClCompile Include="Conntrack-icmp.c" />
>      <ClCompile Include="Conntrack-other.c" />
>      <ClCompile Include="Conntrack-tcp.c" />
>      <ClCompile Include="Conntrack.c" />
> --
> 2.9.0.windows.1
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to