#ifndef included_vnet_sr_packet_h
#define included_vnet_sr_packet_h

#include <vnet/ip/ip.h>

/*
 * ipv6 segment-routing header format
 *
 * Copyright (c) 2013 Cisco and/or its affiliates.
 * 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.
 */

/**
 *  @file
 *  @brief The Segment Routing Header (SRH).
 *
 *  The Segment Routing Header (SRH) is defined in the diagram below.
 *
 *
 *     0                   1                   2                   3
 *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    | Next Header   |  Hdr Ext Len  | Routing Type  | Segments Left |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    | First Segment |             Flags             |  HMAC Key ID  |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |            Segment List[0] (128 bits ipv6 address)            |
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |                                                               |
 *                                  ...
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |            Segment List[n] (128 bits ipv6 address)            |
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |            Policy List[0] (optional)                          |
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |            Policy List[1] (optional)                          |
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |            Policy List[2] (optional)                          |
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *    |                                                               |
 *    |                                                               |
 *    |                                                               |
 *    |                       HMAC (256 bits)                         |
 *    |                        (optional)                             |
 *    |                                                               |
 *    |                                                               |
 *    |                                                               |
 *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *   where:
 *
 *   o  Next Header: 8-bit selector.  Identifies the type of header
 *      immediately following the SRH.
 *
 *   o  Hdr Ext Len: 8-bit unsigned integer, is the length of the SRH
 *      header in 8-octet units, not including the first 8 octets.
 *
 *   o  Routing Type: TBD, to be assigned by IANA (suggested value: 4).
 *
 *   o  Segments Left.  Defined in [RFC2460], it contains the index, in
 *      the Segment List, of the next segment to inspect.  Segments Left
 *      is decremented at each segment and it is used as an index in the
 *      segment list.
 *
 *   o  First Segment: offset in the SRH, not including the first 8 octets
 *      and expressed in 16-octet units, pointing to the last element of
 *      the segment list, which is in fact the first segment of the
 *      segment routing path.
 *
 *   o  Flags: 16 bits of flags.  Following flags are defined:
 *
 *                              1
 *          0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
 *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *         |C|P|R|R|    Policy Flags       |
 *         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *
 *         C-flag: Clean-up flag.  Set when the SRH has to be removed from
 *         the packet when packet reaches the last segment.
 *
 *         P-flag: Protected flag.  Set when the packet has been rerouted
 *         through FRR mechanism by a SR endpoint node.  See Section 6.3
 *         for more details.
 *
 *         R-flags.  Reserved and for future use.
 *
 *         Policy Flags.  Define the type of the IPv6 addresses encoded
 *         into the Policy List (see below).  The following have been
 *         defined:
 *
 *            Bits 4-6: determine the type of the first element after the
 *            segment list.
 *
 *            Bits 7-9: determine the type of the second element.
 *
 *            Bits 10-12: determine the type of the third element.
 *
 *            Bits 13-15: determine the type of the fourth element.
 *
 *         The following values are used for the type:
 *
 *            0x0: Not present.  If value is set to 0x0, it means the
 *            element represented by these bits is not present.
 *
 *            0x1: SR Ingress.
 *
 *            0x2: SR Egress.
 *
 *            0x3: Original Source Address.
 *
 *   o  HMAC Key ID and HMAC field, and their use are defined in
 *      [I-D.vyncke-6man-segment-routing-security].
 *
 *   o  Segment List[n]: 128 bit IPv6 addresses representing the nth
 *      segment in the Segment List.  The Segment List is encoded starting
 *      from the last segment of the path.  I.e., the first element of the
 *      segment list (Segment List [0]) contains the last segment of the
 *      path while the last segment of the Segment List (Segment List[n])
 *      contains the first segment of the path.  The index contained in
 *      "Segments Left" identifies the current active segment.
 *
 *   o  Policy List.  Optional addresses representing specific nodes in
 *      the SR path such as:
 *
 *         SR Ingress: a 128 bit generic identifier representing the
 *         ingress in the SR domain (i.e.: it needs not to be a valid IPv6
 *         address).
 *
 *         SR Egress: a 128 bit generic identifier representing the egress
 *         in the SR domain (i.e.: it needs not to be a valid IPv6
 *         address).
 *
 *         Original Source Address: IPv6 address originally present in the
 *         SA field of the packet.
 *
 *      The segments in the Policy List are encoded after the segment list
 *      and they are optional.  If none are in the SRH, all bits of the
 *      Policy List Flags MUST be set to 0x0.
 */

#ifndef IPPROTO_IPV6_ROUTE
#define IPPROTO_IPV6_ROUTE        43
#endif

#define ROUTING_HEADER_TYPE_SR    4
/**
    @brief SR header struct.
*/
typedef struct
{
  /** Protocol for next header. */
  u8 protocol;

  /**
   * Length of routing header in 8 octet units,
   * not including the first 8 octets
   */
  u8 length;

  /** Type of routing header; type 4 = segement routing */
  u8 type;

  /** Next segment in the segment list */
  u8 segments_left;

  /**
   * Policy list pointer: offset in the SRH of the policy
   * list - in 16-octet units - not including the first 8 octets.
   */
  u8 first_segment;

  /** Flag bits */
#define IP6_SR_HEADER_FLAG_CLEANUP    (0x8000)
  /** Flag bits */
#define IP6_SR_HEADER_FLAG_PROTECTED  (0x4000)
  /** Flag bits */
#define IP6_SR_HEADER_FLAG_RESERVED   (0x3000)
  /** Flag bits */
#define IP6_SR_HEADER_FLAG_PL_ELT_NOT_PRESENT (0x0)
    /** Flag bits */
#define IP6_SR_HEADER_FLAG_PL_ELT_INGRESS_PE (0x1)
    /** Flag bits */
#define IP6_SR_HEADER_FLAG_PL_ELT_EGRESS_PE (0x2)
    /** Flag bits */
#define IP6_SR_HEADER_FLAG_PL_ELT_ORIG_SRC_ADDR (0x3)
  /** values 0x4 - 0x7 are reserved */
  u16 flags;
  u8 hmac_key;

  /** The segment + policy list elts */
  ip6_address_t segments[0];
} __attribute__ ((packed)) ip6_sr_header_t;

static inline int
ip6_sr_policy_list_shift_from_index (int pl_index)
{
  return (-3 * pl_index) + 12;
}

/** pl_index is one-origined */
static inline int
ip6_sr_policy_list_flags (u16 flags_host_byte_order, int pl_index)
{
  int shift;

  if (pl_index <= 0 || pl_index > 4)
    return 0;

  shift = (-3 * pl_index) + 12;
  flags_host_byte_order >>= shift;

  return (flags_host_byte_order & 7);
}

#endif /* included_vnet_sr_packet_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
