summaryrefslogtreecommitdiffstats
path: root/nsh-plugin
diff options
context:
space:
mode:
Diffstat (limited to 'nsh-plugin')
-rw-r--r--nsh-plugin/nsh/nsh.api3
-rw-r--r--nsh-plugin/nsh/nsh.c72
-rw-r--r--nsh-plugin/nsh/nsh.h1
-rw-r--r--nsh-plugin/nsh/nsh_packet.h10
4 files changed, 67 insertions, 19 deletions
diff --git a/nsh-plugin/nsh/nsh.api b/nsh-plugin/nsh/nsh.api
index 1ef3c7b..6beed00 100644
--- a/nsh-plugin/nsh/nsh.api
+++ b/nsh-plugin/nsh/nsh.api
@@ -7,6 +7,7 @@
@param nsp_nsi - Key for nsh_header_t entry to map to. : 24bit NSP 8bit NSI
@param md_type - metadata type [1|2] - only MDType1 supported today
@param ver_o_c - version, O-bit and C-bit (see nsh_packet.h)
+ @param ttl - indicates the maximum SFF hops for an SFP
@param length - header length in n x 32bits, should be 6 for MDtype1
@param next_protocol - next protocol encapsulated behind NSH header: 1=Ethernet, 2=IP4, 3=IP6
@param c1 - 32bit Metadata type1 field (context1)
@@ -22,6 +23,7 @@ define nsh_add_del_entry {
u32 nsp_nsi;
u8 md_type;
u8 ver_o_c;
+ u8 ttl;
u8 length;
u8 next_protocol;
u32 c1;
@@ -55,6 +57,7 @@ define nsh_entry_details {
u32 nsp_nsi;
u8 md_type;
u8 ver_o_c;
+ u8 ttl;
u8 length;
u8 next_protocol;
u32 c1;
diff --git a/nsh-plugin/nsh/nsh.c b/nsh-plugin/nsh/nsh.c
index 8e4ce58..0bbccc0 100644
--- a/nsh-plugin/nsh/nsh.c
+++ b/nsh-plugin/nsh/nsh.c
@@ -250,7 +250,8 @@ u8 * format_nsh_header (u8 * s, va_list * args)
nsh_md2_data_t * nsh_md2 = (nsh_md2_data_t *)(nsh_base + 1);
opt0 = (nsh_md2_data_t *)nsh_md2;
limit0 = (nsh_md2_data_t *) ((u8 *) nsh_md2 +
- (nsh_base->length*4-sizeof(nsh_base_header_t)) );
+ ((nsh_base->length & NSH_LEN_MASK)*4
+ -sizeof(nsh_base_header_t)) );
s = format (s, "nsh ver %d ", (nsh_base->ver_o_c>>6));
if (nsh_base->ver_o_c & NSH_O_BIT)
@@ -259,8 +260,12 @@ u8 * format_nsh_header (u8 * s, va_list * args)
if (nsh_base->ver_o_c & NSH_C_BIT)
s = format (s, "C-set ");
+ s = format (s, "ttl %d ", (nsh_base->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+ (nsh_base->length & NSH_TTL_L2_MASK)>>6);
+
s = format (s, "len %d (%d bytes) md_type %d next_protocol %d\n",
- nsh_base->length, nsh_base->length * 4,
+ (nsh_base->length & NSH_LEN_MASK),
+ (nsh_base->length & NSH_LEN_MASK) * 4,
nsh_base->md_type, nsh_base->next_protocol);
s = format (s, " service path %d service index %d\n",
@@ -905,6 +910,7 @@ int nsh_header_rewrite(nsh_entry_t *nsh_entry)
nsh_base = (nsh_base_header_t *) rw;
nsh_base->ver_o_c = nsh_entry->nsh_base.ver_o_c;
+ nsh_base->length= nsh_entry->nsh_base.length;
nsh_base->md_type = nsh_entry->nsh_base.md_type;
nsh_base->next_protocol = nsh_entry->nsh_base.next_protocol;
nsh_base->nsp_nsi = clib_host_to_net_u32(nsh_entry->nsh_base.nsp_nsi);
@@ -963,7 +969,8 @@ next_tlv_md2:
}
nsh_entry->rewrite = rw;
- nsh_base->length = nsh_entry->rewrite_size >> 2;
+ nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
+ ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
return 0;
}
@@ -1067,6 +1074,7 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
unformat_input_t _line_input, * line_input = &_line_input;
u8 is_add = 1;
u8 ver_o_c = 0;
+ u8 ttl = 63;
u8 length = 0;
u8 md_type = 0;
u8 next_protocol = 1; /* default: ip4 */
@@ -1105,6 +1113,8 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
ver_o_c |= (tmp & 1) << 5;
else if (unformat (line_input, "c-bit %d", &tmp))
ver_o_c |= (tmp & 1) << 4;
+ else if (unformat (line_input, "ttl %d", &ttl))
+ ver_o_c |= (ttl & NSH_LEN_MASK) >> 2;
else if (unformat (line_input, "md-type %d", &tmp))
md_type = tmp;
else if (unformat(line_input, "next-ip4"))
@@ -1197,6 +1207,7 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
a->nsh_entry.tlvs_len = cur_len;
length += (cur_len >> 2);
}
+ length = (length & NSH_LEN_MASK) | ((ttl & 0x3) << 6);
#define _(x) a->nsh_entry.nsh_base.x = x;
foreach_copy_nsh_base_hdr_field;
@@ -1219,7 +1230,7 @@ nsh_add_del_entry_command_fn (vlib_main_t * vm,
VLIB_CLI_COMMAND (create_nsh_entry_command, static) = {
.path = "create nsh entry",
.short_help =
- "create nsh entry {nsp <nn> nsi <nn>} [md-type <nn>]"
+ "create nsh entry {nsp <nn> nsi <nn>} [ttl <nn>] [md-type <nn>]"
" [c1 <nn> c2 <nn> c3 <nn> c4 <nn>] [tlv-ioam-trace] [del]\n",
.function = nsh_add_del_entry_command_fn,
};
@@ -1237,8 +1248,8 @@ static void vl_api_nsh_add_del_entry_t_handler
u8 * data = 0;
a->is_add = mp->is_add;
- a->nsh_entry.nsh_base.ver_o_c = mp->ver_o_c;
- a->nsh_entry.nsh_base.length = mp->length;
+ a->nsh_entry.nsh_base.ver_o_c = (mp->ver_o_c & 0xF0)|((mp->ttl & NSH_LEN_MASK)>>2);
+ a->nsh_entry.nsh_base.length = (mp->length & NSH_LEN_MASK) | ((mp->ttl & 0x3) << 6);
a->nsh_entry.nsh_base.md_type = mp->md_type;
a->nsh_entry.nsh_base.next_protocol = mp->next_protocol;
a->nsh_entry.nsh_base.nsp_nsi = ntohl(mp->nsp_nsi);
@@ -1278,7 +1289,9 @@ static void send_nsh_entry_details
rmp->_vl_msg_id = ntohs((VL_API_NSH_ENTRY_DETAILS)+nm->msg_id_base);
rmp->ver_o_c = t->nsh_base.ver_o_c;
- rmp->length = t->nsh_base.length;
+ rmp->ttl = (t->nsh_base.ver_o_c & NSH_TTL_H4_MASK)<<2 |
+ (t->nsh_base.length & NSH_TTL_L2_MASK)>>6;
+ rmp->length = t->nsh_base.length & NSH_LEN_MASK;
rmp->md_type = t->nsh_base.md_type;
rmp->next_protocol = t->nsh_base.next_protocol;
rmp->nsp_nsi = htonl(t->nsh_base.nsp_nsi);
@@ -1506,8 +1519,8 @@ next_tlv_md2:
/* update nsh header's length */
nsh_base = (nsh_base_header_t *)nsh_entry->rewrite;
- nsh_base->length = (nsh_entry->rewrite_size >> 2);
-
+ nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
+ ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
return;
}
@@ -1574,7 +1587,8 @@ next_tlv_md2:
/* update nsh header's length */
nsh_base = (nsh_base_header_t *)nsh_entry->rewrite;
- nsh_base->length = (nsh_entry->rewrite_size >> 2);
+ nsh_base->length = (nsh_base->length & NSH_TTL_L2_MASK) |
+ ((nsh_entry->rewrite_size >> 2) & NSH_LEN_MASK);
return;
}
@@ -1652,6 +1666,7 @@ nsh_input_map (vlib_main_t * vm,
nsh_base_header_t * hdr0 = 0, *hdr1 = 0;
u32 header_len0 = 0, header_len1 = 0;
u32 nsp_nsi0, nsp_nsi1;
+ u32 ttl0, ttl1;
u32 error0, error1;
nsh_map_t * map0 = 0, *map1 = 0;
nsh_entry_t * nsh_entry0 = 0, *nsh_entry1 = 0;
@@ -1695,7 +1710,15 @@ nsh_input_map (vlib_main_t * vm,
if(node_type == NSH_INPUT_TYPE)
{
nsp_nsi0 = hdr0->nsp_nsi;
- header_len0 = hdr0->length * 4;
+ header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
+ ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+ (hdr0->length & NSH_TTL_L2_MASK)>>6;
+ ttl0 = ttl0 - 1;
+ if (PREDICT_FALSE(ttl0 == 0))
+ {
+ error0 = NSH_NODE_ERROR_INVALID_TTL;
+ goto trace0;
+ }
}
else if(node_type == NSH_CLASSIFIER_TYPE)
{
@@ -1742,7 +1765,15 @@ nsh_input_map (vlib_main_t * vm,
if(node_type == NSH_INPUT_TYPE)
{
nsp_nsi1 = hdr1->nsp_nsi;
- header_len1 = hdr1->length * 4;
+ header_len1 = (hdr1->length & NSH_LEN_MASK) * 4;
+ ttl1 = (hdr1->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+ (hdr1->length & NSH_TTL_L2_MASK)>>6;
+ ttl1 = ttl1 - 1;
+ if (PREDICT_FALSE(ttl1 == 0))
+ {
+ error1 = NSH_NODE_ERROR_INVALID_TTL;
+ goto trace1;
+ }
}
else if(node_type == NSH_CLASSIFIER_TYPE)
{
@@ -1886,7 +1917,7 @@ nsh_input_map (vlib_main_t * vm,
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
{
nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
- clib_memcpy ( &(tr->trace_data), hdr0, (hdr0->length*4) );
+ clib_memcpy ( &(tr->trace_data), hdr0, ((hdr0->length & NSH_LEN_MASK)*4) );
}
/* Process packet 1 */
@@ -1990,7 +2021,7 @@ nsh_input_map (vlib_main_t * vm,
if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
{
nsh_input_trace_t *tr = vlib_add_trace(vm, node, b1, sizeof(*tr));
- clib_memcpy ( &(tr->trace_data), hdr1, (hdr1->length*4) );
+ clib_memcpy ( &(tr->trace_data), hdr1, ((hdr1->length & NSH_LEN_MASK)*4) );
}
vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next,
@@ -2007,6 +2038,7 @@ nsh_input_map (vlib_main_t * vm,
nsh_base_header_t * hdr0 = 0;
u32 header_len0 = 0;
u32 nsp_nsi0;
+ u32 ttl0;
u32 error0;
nsh_map_t * map0 = 0;
nsh_entry_t * nsh_entry0 = 0;
@@ -2032,7 +2064,15 @@ nsh_input_map (vlib_main_t * vm,
if(node_type == NSH_INPUT_TYPE)
{
nsp_nsi0 = hdr0->nsp_nsi;
- header_len0 = hdr0->length * 4;
+ header_len0 = (hdr0->length & NSH_LEN_MASK) * 4;
+ ttl0 = (hdr0->ver_o_c & NSH_TTL_H4_MASK)<<2 |
+ (hdr0->length & NSH_TTL_L2_MASK)>>6;
+ ttl0 = ttl0 - 1;
+ if (PREDICT_FALSE(ttl0 == 0))
+ {
+ error0 = NSH_NODE_ERROR_INVALID_TTL;
+ goto trace00;
+ }
}
else if(node_type == NSH_CLASSIFIER_TYPE)
{
@@ -2177,7 +2217,7 @@ nsh_input_map (vlib_main_t * vm,
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
{
nsh_input_trace_t *tr = vlib_add_trace(vm, node, b0, sizeof(*tr));
- clib_memcpy ( &(tr->trace_data[0]), hdr0, (hdr0->length*4) );
+ clib_memcpy ( &(tr->trace_data[0]), hdr0, ((hdr0->length & NSH_LEN_MASK)*4) );
}
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
diff --git a/nsh-plugin/nsh/nsh.h b/nsh-plugin/nsh/nsh.h
index 8605fc7..d763f87 100644
--- a/nsh-plugin/nsh/nsh.h
+++ b/nsh-plugin/nsh/nsh.h
@@ -186,6 +186,7 @@ _(NO_ENTRY, "no entry for nsh key") \
_(NO_PROXY, "no proxy for transport key") \
_(INVALID_NEXT_PROTOCOL, "invalid next protocol") \
_(INVALID_OPTIONS, "invalid md2 options") \
+_(INVALID_TTL, "ttl equals zero") \
typedef enum {
#define _(sym,str) NSH_NODE_ERROR_##sym,
diff --git a/nsh-plugin/nsh/nsh_packet.h b/nsh-plugin/nsh/nsh_packet.h
index 101652a..9d6237a 100644
--- a/nsh-plugin/nsh/nsh_packet.h
+++ b/nsh-plugin/nsh/nsh_packet.h
@@ -22,7 +22,7 @@
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |Ver|O|C|R|R|R|R|R|R| Length | MD Type | Next Protocol |
+ * |Ver|O|C| TTL | Length | MD Type | Next Protocol |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
@@ -69,8 +69,8 @@
*/
typedef CLIB_PACKED(struct {
- u8 ver_o_c;
- u8 length;
+ u8 ver_o_c; //TTL: high 4 bit
+ u8 length; //TTL: low 2 bit
u8 md_type;
u8 next_protocol;
u32 nsp_nsi; // nsp 24 bits, nsi 8 bits
@@ -104,6 +104,10 @@ typedef CLIB_PACKED(struct {
#define NSH_O_BIT (1<<5)
#define NSH_C_BIT (1<<4)
+#define NSH_TTL_H4_MASK 0xF
+#define NSH_TTL_L2_MASK 0xC0
+#define NSH_LEN_MASK 0x3F
+
/* Network byte order shift / mask */
#define NSH_NSI_MASK 0xFF
#define NSH_NSP_MASK (0x00FFFFFF)