#!/usr/bin/env python import unittest from logging import * from framework import VppTestCase, VppTestRunner from vpp_sub_interface import VppDot1QSubint from vpp_gre_interface import VppGreInterface, VppGre6Interface from vpp_ip_route import VppIpRoute, VppRoutePath, DpoProto, VppIpTable from vpp_papi_provider import L2_VTR_OP from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q, GRE from scapy.layers.inet import IP, UDP from scapy.layers.inet6 import IPv6 from scapy.volatile import RandMAC, RandIP from util import ppp, ppc class TestGRE(VppTestCase): """ GRE Test Case """ @classmethod def setUpClass(cls): super(TestGRE, cls).setUpClass() def setUp(self): super(TestGRE, self).setUp() # create 3 pg interfaces - set one in a non-default table. self.create_pg_interfaces(range(3)) self.tbl = VppIpTable(self, 1) self.tbl.add_vpp_config() self.pg1.set_table_ip4(1) for i in self.pg_interfaces: i.admin_up() self.pg0.config_ip4() self.pg0.resolve_arp() self.pg1.config_ip4() self.pg1.resolve_arp() self.pg2.config_ip6() self.pg2.resolve_ndp() def tearDown(self): for i in self.pg_interfaces: i.unconfig_ip4() i.unconfig_ip6() i.admin_down() self.pg1.set_table_ip4(0) super(TestGRE, self).tearDown() def create_stream_ip4(self, src_if, src_ip, dst_ip): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IP(src=src_ip, dst=dst_ip) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def create_stream_ip6(self, src_if, src_ip, dst_ip): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IPv6(src=src_ip, dst=dst_ip) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def create_tunnel_stream_4o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IP(src=tunnel_src, dst=tunnel_dst) / GRE() / IP(src=src_ip, dst=dst_ip) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def create_tunnel_stream_6o4(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IP(src=tunnel_src, dst=tunnel_dst) / GRE() / IPv6(src=src_ip, dst=dst_ip) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def create_tunnel_stream_6o6(self, src_if, tunnel_src, tunnel_dst, src_ip, dst_ip): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IPv6(src=tunnel_src, dst=tunnel_dst) / GRE() / IPv6(src=src_ip, dst=dst_ip) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def create_tunnel_stream_l2o4(self, src_if, tunnel_src, tunnel_dst): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IP(src=tunnel_src, dst=tunnel_dst) / GRE() / Ether(dst=RandMAC('*:*:*:*:*:*'), src=RandMAC('*:*:*:*:*:*')) / IP(src=str(RandIP()), dst=str(RandIP())) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def create_tunnel_stream_vlano4(self, src_if, tunnel_src, tunnel_dst, vlan): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if, src_if) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / IP(src=tunnel_src, dst=tunnel_dst) / GRE() / Ether(dst=RandMAC('*:*:*:*:*:*'), src=RandMAC('*:*:*:*:*:*')) / Dot1Q(vlan=vlan) / IP(src=str(RandIP()), dst=str(RandIP())) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts def verify_tunneled_4o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IP] rx_ip = rx[IP] self.assertEqual(rx_ip.src, tunnel_src) self.assertEqual(rx_ip.dst, tunnel_dst) rx_gre = rx[GRE] rx_ip = rx_gre[IP] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) # IP processing post pop has decremented the TTL self.assertEqual(rx_ip.ttl + 1, tx_ip.ttl) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise def verify_tunneled_6o6(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i] tx_ip = tx[IPv6] rx_ip = rx[IPv6] self.assertEqual(rx_ip.src, tunnel_src) self.assertEqual(rx_ip.dst, tunnel_dst) rx_gre = GRE(str(rx_ip[IPv6].payload)) rx_ip = rx_gre[IPv6] self.assertEqual(rx_ip.src, tx_ip.src) self.assertEqual(rx_ip.dst, tx_ip.dst) except: self.logger.error(ppp("Rx:", rx)) self.logger.error(ppp("Tx:", tx)) raise def verify_tunneled_l2o4(self, src_if, capture, sent, tunnel_src, tunnel_dst): self.assertEqual(len(capture), len(sent)) for i in range(len(capture)): try: tx = sent[i] rx = capture[i]
/*
 * pg.c: packet generator for L2TPv3 header
 *
 * 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.
 */

#include <vlib/vlib.h>
#include <vnet/pg/pg.h>
#include <vnet/l2tp/l2tp.h>

typedef struct
{
  pg_edit_t session_id;
  pg_edit_t cookie;
} pg_l2tp_header_t;

typedef struct
{
  pg_edit_t l2_sublayer;
} pg_l2tp_header_l2_sublayer_t;

static inline void
pg_l2tp_header_init (pg_l2tp_header_t * e)
{
  pg_edit_init (&e->session_id, l2tpv3_header_t, session_id);
  pg_edit_init (&e->cookie, l2tpv3_header_t, cookie);
}

uword
unformat_pg_l2tp_header (unformat_input_t * input, va_list * args)
{
  pg_stream_t *s = va_arg (*args, pg_stream_t *);
  pg_l2tp_header_t *h;
  u32 group_index, error;
  vlib_main_t *vm = vlib_get_main ();

  h = pg_create_edit_group (s, sizeof (h[0]),
			    sizeof (l2tpv3_header_t) - sizeof (u32),
			    &group_index);
  pg_l2tp_header_init (h);

  error = 1;

  /* session id and cookie are required */
  if (!unformat (input, "L2TP: session_id %U cookie %U",
		 unformat_pg_edit, unformat_pg_number, &h->session_id,
		 unformat_pg_edit, unformat_pg_number, &h->cookie))
    {
      goto done;
    }

  /* "l2_sublayer <value>" is optional */
  if (unformat (input, "l2_sublayer"))
    {
      pg_l2tp_header_l2_sublayer_t *h2;

      h2 = pg_add_edits (s, sizeof (h2[0]), sizeof (u32), group_index);
      pg_edit_init (&h2->l2_sublayer, l2tpv3_header_t, l2_specific_sublayer);
      if (!unformat_user (input, unformat_pg_edit,
			  unformat_pg_number, &h2->l2_sublayer))
	{
	  goto done;
	}
    }

  /* Parse an ethernet header if it is present */
  {
    pg_node_t *pg_node = 0;
    vlib_node_t *eth_lookup_node;

    eth_lookup_node = vlib_get_node_by_name (vm, (u8 *) "ethernet-input");
    ASSERT (eth_lookup_node);

    pg_node = pg_get_node (eth_lookup_node->index);

    if (pg_node && pg_node->unformat_edit
	&& unformat_user (input, pg_node->unformat_edit, s))
      ;
  }

  error = 0;

done:
  if (error)
    pg_free_edit_group (s);
  return error == 0;
}

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