#include <vnet/devices/af_packet/af_packet.h>
#include <vnet/policer/policer.h>
#include <vnet/devices/netmap/netmap.h>
+#include <vnet/flow/flow_report.h>
#undef BIHASH_TYPE
#undef __included_bihash_template_h__
_(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \
_(CLASSIFY_TABLE_INFO,classify_table_info) \
_(CLASSIFY_SESSION_DUMP,classify_session_dump) \
-_(CLASSIFY_SESSION_DETAILS,classify_session_details)
+_(CLASSIFY_SESSION_DETAILS,classify_session_details) \
+_(IPFIX_ENABLE,ipfix_enable) \
+_(IPFIX_DUMP,ipfix_dump)
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
uword * p;
clib_error_t * e;
u32 ai;
- ip_adjacency_t *nh_adj, *add_adj = 0;
+ ip_adjacency_t *adj;
p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
if (!p) {
fib_index = p[0];
}
- if (pool_is_free_index (vnm->interface_main.sw_interfaces,
+ if (~0 != mp->next_hop_sw_if_index &&
+ pool_is_free_index (vnm->interface_main.sw_interfaces,
ntohl(mp->next_hop_sw_if_index)))
return VNET_API_ERROR_NO_MATCHING_INTERFACE;
sizeof (next_hop_address.data));
/* Arp for the next_hop if necessary */
- if (mp->is_add && mp->resolve_if_needed) {
+ if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) {
u32 lookup_result;
ip_adjacency_t * adj;
else if (mp->is_local)
ai = lm->local_adj_index;
else if (mp->is_classify) {
- ip_adjacency_t cadj;
- memset(&cadj, 0, sizeof(cadj));
- cadj.lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY;
- cadj.classify.table_index = ntohl(mp->classify_table_index);
- if (pool_is_free_index (cm->tables, cadj.classify.table_index)) {
+ if (pool_is_free_index (cm->tables, ntohl(mp->classify_table_index))) {
dsunlock(sm);
return VNET_API_ERROR_NO_SUCH_TABLE;
}
- vec_add1 (add_adj, cadj);
- goto do_add_del;
- }
- else {
- ai = ip4_fib_lookup_with_table
- (im, fib_index, &next_hop_address,
- 1 /* disable default route */);
- if (ai == lm->miss_adj_index) {
- dsunlock(sm);
- return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
- }
- }
+ adj = ip_add_adjacency (lm,
+ /* template */ 0,
+ /* block size */ 1,
+ &ai);
- nh_adj = ip_get_adjacency (lm, ai);
- if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
- nh_adj->arp.next_hop.ip4.as_u32 == 0) {
- /* the next-hop resovles via a glean adj. create and use
- * a ARP adj for the next-hop */
- a.adj_index = vnet_arp_glean_add(fib_index, &next_hop_address);
- a.add_adj = NULL;
- a.n_add_adj = 0;
- ip4_add_del_route (im, &a);
-
- goto done;
+ adj->lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY;
+ adj->classify.table_index = ntohl(mp->classify_table_index);
}
- vec_add1 (add_adj, nh_adj[0]);
- if (mp->lookup_in_vrf) {
+ else if (mp->lookup_in_vrf) {
p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
- if (p)
- add_adj[0].explicit_fib_index = p[0];
+ if (p) {
+ adj = ip_add_adjacency (lm,
+ /* template */ 0,
+ /* block size */ 1,
+ &ai);
+ adj->explicit_fib_index = p[0];
+ }
else {
- vec_free (add_adj);
dsunlock(sm);
- return VNET_API_ERROR_NO_SUCH_INNER_FIB;
- }
- }
+ return VNET_API_ERROR_NO_SUCH_INNER_FIB;
+ }
+ }
+ else
+ ai = ip4_route_get_next_hop_adj (im,
+ fib_index,
+ &next_hop_address,
+ ntohl(mp->next_hop_sw_if_index),
+ fib_index);
+
+ if (ai == lm->miss_adj_index) {
+ dsunlock(sm);
+ return VNET_API_ERROR_NO_SUCH_INNER_FIB;
+ }
} else {
ip_adjacency_t * adj;
int disable_default_route = 1;
}
}
-do_add_del:
- a.adj_index = ~0;
- a.add_adj = add_adj;
- a.n_add_adj = vec_len(add_adj);
+ a.adj_index = ai;
ip4_add_del_route (im, &a);
- vec_free (add_adj);
-
-done:
dsunlock (sm);
return 0;
}
u32 fib_index;
uword * p;
clib_error_t * e;
- ip_adjacency_t * nh_adj, * add_adj = 0;
+ ip_adjacency_t *adj = 0;
u32 ai;
p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
fib_index = p[0];
}
- if (pool_is_free_index (vnm->interface_main.sw_interfaces,
+ if (~0 != mp->next_hop_sw_if_index &&
+ pool_is_free_index (vnm->interface_main.sw_interfaces,
ntohl(mp->next_hop_sw_if_index)))
return VNET_API_ERROR_NO_MATCHING_INTERFACE;
sizeof (next_hop_address.as_u8));
/* Arp for the next_hop if necessary */
- if (mp->is_add && mp->resolve_if_needed) {
+ if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) {
u32 lookup_result;
ip_adjacency_t * adj;
ai = lm->drop_adj_index;
else if (mp->is_local)
ai = lm->local_adj_index;
- else {
- ai = ip6_fib_lookup_with_table
- (im, fib_index, &next_hop_address);
- if (ai == lm->miss_adj_index) {
- dsunlock(sm);
- return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
- }
- }
-
- nh_adj = ip_get_adjacency (lm, ai);
- vec_add1 (add_adj, nh_adj[0]);
- if (mp->lookup_in_vrf) {
+ else if (mp->lookup_in_vrf) {
p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
- if (p)
- add_adj[0].explicit_fib_index = p[0];
+ if (p) {
+ adj = ip_add_adjacency (lm,
+ /* template */ 0,
+ /* block size */ 1,
+ &ai);
+ adj->explicit_fib_index = p[0];
+ }
else {
- vec_free (add_adj);
- dsunlock(sm);
+ dsunlock(sm);
return VNET_API_ERROR_NO_SUCH_INNER_FIB;
- }
- }
+ }
+ }
+ else
+ ai = ip6_route_get_next_hop_adj (im,
+ fib_index,
+ &next_hop_address,
+ ntohl(mp->next_hop_sw_if_index),
+ fib_index);
+ if (ai == lm->miss_adj_index) {
+ dsunlock(sm);
+ return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
+ }
} else {
ip_adjacency_t * adj;
}
}
- a.adj_index = ~0;
- a.add_adj = add_adj;
- a.n_add_adj = vec_len(add_adj);
+ a.adj_index = ai;
ip6_add_del_route (im, &a);
- vec_free (add_adj);
-
dsunlock (sm);
return 0;
}
u32 bd_index;
u32 static_mac;
u32 filter_mac;
+ u32 bvi_mac;
uword * p;
mac = mp->mac;
}
static_mac = mp->static_mac ? 1 : 0;
filter_mac = mp->filter_mac ? 1 : 0;
+ bvi_mac = mp->bvi_mac ? 1 : 0;
l2fib_add_entry(mac, bd_index, sw_if_index, static_mac, filter_mac,
- 0 /* bvi_mac */);
+ bvi_mac);
} else {
l2fib_del_entry(mac, bd_index);
}
typedef CLIB_PACKED(struct
{
u8 is_ip4; /**< is locator an IPv4 address */
+ u8 priority; /**< locator priority */
+ u8 weight; /**< locator weight */
u8 addr[16]; /**< IPv4/IPv6 address */
}) rloc_t;
r->is_ip4 ? IP4 : IP6);
gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
- /* TODO fix API to pass priority and weight */
- rloc.priority = 1;
- rloc.weight = 1;
+ rloc.priority = r->priority;
+ rloc.weight = r->weight;
vec_add1 (rlocs, rloc);
}
r->is_ip4 ? IP4 : IP6);
gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128;
gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX;
- /* TODO fix API to pass priority and weight */
- rloc.priority = 1;
- rloc.weight = 1;
+ rloc.priority = r->priority;
+ rloc.weight = r->weight;
vec_add1 (a->locators, rloc);
}
}));
}
+static void vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t *mp)
+{
+ vlib_main_t *vm = vlib_get_main();
+ flow_report_main_t * frm = &flow_report_main;
+ vl_api_ipfix_enable_reply_t *rmp;
+ ip4_address_t collector, src;
+ u16 collector_port = UDP_DST_PORT_ipfix;
+ u32 path_mtu;
+ u32 template_interval;
+ u32 fib_id;
+ u32 fib_index = ~0;
+ int rv = 0;
+
+ memcpy(collector.data, mp->collector_address, sizeof(collector.data));
+ collector_port = ntohs(mp->collector_port);
+ if (collector_port == (u16)~0)
+ collector_port = UDP_DST_PORT_ipfix;
+ memcpy(src.data, mp->src_address, sizeof(src.data));
+ fib_id = ntohl(mp->vrf_id);
+
+ ip4_main_t * im = &ip4_main;
+ uword * p = hash_get (im->fib_index_by_table_id, fib_id);
+ if (! p) {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto out;
+ }
+ fib_index = p[0];
+
+ path_mtu = ntohl(mp->path_mtu);
+ if (path_mtu == ~0)
+ path_mtu = 512; // RFC 7011 section 10.3.3.
+ template_interval = ntohl(mp->template_interval);
+ if (template_interval == ~0)
+ template_interval = 20;
+
+ if (collector.as_u32 == 0) {
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto out;
+ }
+
+ if (src.as_u32 == 0) {
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto out;
+ }
+
+ if (path_mtu > 1450 /* vpp does not support fragmentation */) {
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto out;
+ }
+
+ if (path_mtu < 68) {
+ rv = VNET_API_ERROR_INVALID_VALUE;
+ goto out;
+ }
+
+ /* Reset report streams if we are reconfiguring IP addresses */
+ if (frm->ipfix_collector.as_u32 != collector.as_u32 ||
+ frm->src_address.as_u32 != src.as_u32 ||
+ frm->collector_port != collector_port)
+ vnet_flow_reports_reset(frm);
+
+ frm->ipfix_collector.as_u32 = collector.as_u32;
+ frm->collector_port = collector_port;
+ frm->src_address.as_u32 = src.as_u32;
+ frm->fib_index = fib_index;
+ frm->path_mtu = path_mtu;
+ frm->template_interval = template_interval;
+
+ /* Turn on the flow reporting process */
+ vlib_process_signal_event (vm, flow_report_process_node.index,
+ 1, 0);
+
+out:
+ REPLY_MACRO(VL_API_IPFIX_ENABLE_REPLY);
+}
+
+static void vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t *mp)
+{
+ flow_report_main_t * frm = &flow_report_main;
+ unix_shared_memory_queue_t * q;
+ vl_api_ipfix_details_t *rmp;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs(VL_API_IPFIX_DETAILS);
+ rmp->context = mp->context;
+ memcpy(rmp->collector_address, frm->ipfix_collector.data,
+ sizeof(frm->ipfix_collector.data));
+ rmp->collector_port = htons(frm->collector_port);
+ memcpy(rmp->src_address, frm->src_address.data,
+ sizeof(frm->src_address.data));
+ rmp->fib_index = htonl(frm->fib_index);
+ rmp->path_mtu = htonl(frm->path_mtu);
+ rmp->template_interval = htonl(frm->template_interval);
+
+ vl_msg_api_send_shmem (q, (u8 *)&rmp);
+}
+
#define BOUNCE_HANDLER(nn) \
static void vl_api_##nn##_t_handler ( \
vl_api_##nn##_t *mp) \