Reenable dhcp client detect when lease expires

We disable the client detect feature when we bind a DHCP address. Turn
it back on again when the lease expires.  Otherwise, if the DHCP
server replies after an outage, we'll never see the reply.

Add dhcp packet tx counters, by packet type

Change-Id: Id54b05647d5d7bd8d3ab99e6584ee86d9e4ff7f9
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c
index 511b23c..330b38d 100644
--- a/src/vnet/dhcp/client.c
+++ b/src/vnet/dhcp/client.c
@@ -21,6 +21,29 @@
 static u8 *format_dhcp_client_state (u8 * s, va_list * va);
 static vlib_node_registration_t dhcp_client_process_node;
 
+#define foreach_dhcp_client_process_stat        \
+_(DISCOVER, "DHCP discover packets sent")       \
+_(OFFER, "DHCP offer packets sent")             \
+_(REQUEST, "DHCP request packets sent")         \
+_(ACK, "DHCP ack packets sent")
+
+typedef enum
+{
+#define _(sym,str) DHCP_STAT_##sym,
+  foreach_dhcp_client_process_stat
+#undef _
+    DHCP_STAT_UNKNOWN,
+  DHCP_STAT_N_STAT,
+} sample_error_t;
+
+static char *dhcp_client_process_stat_strings[] = {
+#define _(sym,string) string,
+  foreach_dhcp_client_process_stat
+#undef _
+    "DHCP unknown packets sent",
+};
+
+
 static void
 dhcp_client_acquire_address (dhcp_client_main_t * dcm, dhcp_client_t * c)
 {
@@ -296,6 +319,7 @@
   vlib_frame_t *f;
   dhcp_option_t *o;
   u16 udp_length, ip_length;
+  u32 counter_index;
 
   /* Interface(s) down? */
   if ((hw->flags & VNET_HW_INTERFACE_FLAG_LINK_UP) == 0)
@@ -474,6 +498,19 @@
 
   udp_length = ip_length - (sizeof (*ip));
   udp->length = clib_host_to_net_u16 (udp_length);
+
+  switch (type)
+    {
+#define _(a,b) case DHCP_PACKET_##a: {counter_index = DHCP_STAT_##a; break;}
+      foreach_dhcp_client_process_stat
+#undef _
+    default:
+      counter_index = DHCP_STAT_UNKNOWN;
+      break;
+    }
+
+  vlib_node_increment_counter (vm, dhcp_client_process_node.index,
+			       counter_index, 1);
 }
 
 static int
@@ -532,6 +569,7 @@
 
   if (now > c->lease_expires)
     {
+      /* Remove the default route */
       if (c->router_address.as_u32)
 	{
 	  fib_prefix_t all_0s = {
@@ -549,7 +587,7 @@
 				       DPO_PROTO_IP4, &nh, c->sw_if_index, ~0,
 				       1, FIB_ROUTE_PATH_FLAG_NONE);
 	}
-
+      /* Remove the interface address */
       dhcp_client_release_address (dcm, c);
       c->state = DHCP_DISCOVER;
       c->next_transmit = now;
@@ -560,6 +598,15 @@
       c->router_address.as_u32 = 0;
       c->lease_renewal_interval = 0;
       c->dhcp_server.as_u32 = 0;
+      /*
+       * We disable the client detect feature when we bind a
+       * DHCP address. Turn it back on again here.
+       * Otherwise, if the DHCP server replies after an outage,
+       * we'll never see it.
+       */
+      vnet_feature_enable_disable ("ip4-unicast",
+				   "ip4-dhcp-client-detect",
+				   c->sw_if_index, 1, 0, 0);
       return 1;
     }
   return 0;
@@ -664,6 +711,8 @@
     .type = VLIB_NODE_TYPE_PROCESS,
     .name = "dhcp-client-process",
     .process_log2_n_stack_bytes = 16,
+    .n_errors = ARRAY_LEN(dhcp_client_process_stat_strings),
+    .error_strings = dhcp_client_process_stat_strings,
 };
 /* *INDENT-ON* */