Revert "Revert "Proto API for LB request/responses""
diff --git a/src/core/client_config/lb_policies/load_balancer_api.c b/src/core/client_config/lb_policies/load_balancer_api.c
new file mode 100644
index 0000000..a6b5785
--- /dev/null
+++ b/src/core/client_config/lb_policies/load_balancer_api.c
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/client_config/lb_policies/load_balancer_api.h"
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+#include <grpc/support/alloc.h>
+
+typedef struct decode_serverlist_arg {
+  int first_pass;
+  int i;
+  size_t num_servers;
+  grpc_grpclb_server **servers;
+} decode_serverlist_arg;
+
+/* invoked once for every Server in ServerList */
+static bool decode_serverlist(pb_istream_t *stream, const pb_field_t *field,
+                              void **arg) {
+  decode_serverlist_arg *dec_arg = *arg;
+  if (dec_arg->first_pass != 0) { /* first pass */
+    grpc_grpclb_server server;
+    if (!pb_decode(stream, grpc_lb_v0_Server_fields, &server)) {
+      return false;
+    }
+    dec_arg->num_servers++;
+  } else { /* second pass */
+    grpc_grpclb_server *server = gpr_malloc(sizeof(grpc_grpclb_server));
+    GPR_ASSERT(dec_arg->num_servers > 0);
+    if (dec_arg->i == 0) { /* first iteration of second pass */
+      dec_arg->servers =
+          gpr_malloc(sizeof(grpc_grpclb_server *) * dec_arg->num_servers);
+    }
+    if (!pb_decode(stream, grpc_lb_v0_Server_fields, server)) {
+      return false;
+    }
+    dec_arg->servers[dec_arg->i++] = server;
+  }
+
+  return true;
+}
+
+grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name) {
+  grpc_grpclb_request *req = gpr_malloc(sizeof(grpc_grpclb_request));
+
+  req->has_client_stats = 0; /* TODO(dgq): add support for stats once defined */
+  req->has_initial_request = 1;
+  req->initial_request.has_name = 1;
+  strncpy(req->initial_request.name, lb_service_name,
+          GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH);
+  return req;
+}
+
+gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request) {
+  size_t encoded_length;
+  pb_ostream_t sizestream;
+  pb_ostream_t outputstream;
+  gpr_slice slice;
+  memset(&sizestream, 0, sizeof(pb_ostream_t));
+  pb_encode(&sizestream, grpc_lb_v0_LoadBalanceRequest_fields, request);
+  encoded_length = sizestream.bytes_written;
+
+  slice = gpr_slice_malloc(encoded_length);
+  outputstream =
+      pb_ostream_from_buffer(GPR_SLICE_START_PTR(slice), encoded_length);
+  GPR_ASSERT(pb_encode(&outputstream, grpc_lb_v0_LoadBalanceRequest_fields,
+                       request) != 0);
+  return slice;
+}
+
+void grpc_grpclb_request_destroy(grpc_grpclb_request *request) {
+  gpr_free(request);
+}
+
+grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response) {
+  bool status;
+  pb_istream_t stream =
+      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
+                             GPR_SLICE_LENGTH(encoded_response));
+  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
+  memset(res, 0, sizeof(*res));
+  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  GPR_ASSERT(status == true);
+  return res;
+}
+
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+    gpr_slice encoded_response) {
+  grpc_grpclb_serverlist *sl = gpr_malloc(sizeof(grpc_grpclb_serverlist));
+  bool status;
+  decode_serverlist_arg arg;
+  pb_istream_t stream =
+      pb_istream_from_buffer(GPR_SLICE_START_PTR(encoded_response),
+                             GPR_SLICE_LENGTH(encoded_response));
+  pb_istream_t stream_at_start = stream;
+  grpc_grpclb_response *res = gpr_malloc(sizeof(grpc_grpclb_response));
+  memset(res, 0, sizeof(*res));
+  memset(&arg, 0, sizeof(decode_serverlist_arg));
+
+  res->server_list.servers.funcs.decode = decode_serverlist;
+  res->server_list.servers.arg = &arg;
+  arg.first_pass = 1;
+  status = pb_decode(&stream, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  GPR_ASSERT(status == true);
+  GPR_ASSERT(arg.num_servers > 0);
+
+  arg.first_pass = 0;
+  status =
+      pb_decode(&stream_at_start, grpc_lb_v0_LoadBalanceResponse_fields, res);
+  GPR_ASSERT(status == true);
+  GPR_ASSERT(arg.servers != NULL);
+
+  sl->num_servers = arg.num_servers;
+  sl->servers = arg.servers;
+  if (res->server_list.has_expiration_interval) {
+    sl->expiration_interval = res->server_list.expiration_interval;
+  }
+  grpc_grpclb_response_destroy(res);
+  return sl;
+}
+
+void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist) {
+  size_t i;
+  for (i = 0; i < serverlist->num_servers; i++) {
+    gpr_free(serverlist->servers[i]);
+  }
+  gpr_free(serverlist->servers);
+  gpr_free(serverlist);
+}
+
+void grpc_grpclb_response_destroy(grpc_grpclb_response *response) {
+  gpr_free(response);
+}
diff --git a/src/core/client_config/lb_policies/load_balancer_api.h b/src/core/client_config/lb_policies/load_balancer_api.h
new file mode 100644
index 0000000..4dbe1d6
--- /dev/null
+++ b/src/core/client_config/lb_policies/load_balancer_api.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H
+#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H
+
+#include <grpc/support/slice_buffer.h>
+
+#include "src/core/client_config/lb_policy_factory.h"
+#include "src/core/proto/grpc/lb/v0/load_balancer.pb.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define GRPC_GRPCLB_SERVICE_NAME_MAX_LENGTH 128
+
+typedef grpc_lb_v0_LoadBalanceRequest grpc_grpclb_request;
+typedef grpc_lb_v0_LoadBalanceResponse grpc_grpclb_response;
+typedef grpc_lb_v0_Server grpc_grpclb_server;
+typedef grpc_lb_v0_Duration grpc_grpclb_duration;
+typedef struct grpc_grpclb_serverlist {
+  grpc_grpclb_server **servers;
+  size_t num_servers;
+  grpc_grpclb_duration expiration_interval;
+} grpc_grpclb_serverlist;
+
+/** Create a request for a gRPC LB service under \a lb_service_name */
+grpc_grpclb_request *grpc_grpclb_request_create(const char *lb_service_name);
+
+/** Protocol Buffers v3-encode \a request */
+gpr_slice grpc_grpclb_request_encode(const grpc_grpclb_request *request);
+
+/** Destroy \a request */
+void grpc_grpclb_request_destroy(grpc_grpclb_request *request);
+
+/** Parse (ie, decode) the bytes in \a encoded_response as a \a
+ * grpc_grpclb_response */
+grpc_grpclb_response *grpc_grpclb_response_parse(gpr_slice encoded_response);
+
+/** Destroy \a serverlist */
+void grpc_grpclb_destroy_serverlist(grpc_grpclb_serverlist *serverlist);
+
+/** Parse the list of servers from an encoded \a grpc_grpclb_response */
+grpc_grpclb_serverlist *grpc_grpclb_response_parse_serverlist(
+    gpr_slice encoded_response);
+
+/** Destroy \a response */
+void grpc_grpclb_response_destroy(grpc_grpclb_response *response);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_LB_POLICIES_LOAD_BALANCER_API_H */
diff --git a/src/core/proto/grpc/lb/v0/load_balancer.pb.c b/src/core/proto/grpc/lb/v0/load_balancer.pb.c
new file mode 100644
index 0000000..bbb6fa8
--- /dev/null
+++ b/src/core/proto/grpc/lb/v0/load_balancer.pb.c
@@ -0,0 +1,150 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-0.3.4-dev */
+
+#include "src/core/proto/grpc/lb/v0/load_balancer.pb.h"
+
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+const pb_field_t grpc_lb_v0_Duration_fields[3] = {
+    PB_FIELD(1, INT64, OPTIONAL, STATIC, FIRST, grpc_lb_v0_Duration, seconds,
+             seconds, 0),
+    PB_FIELD(2, INT32, OPTIONAL, STATIC, OTHER, grpc_lb_v0_Duration, nanos,
+             seconds, 0),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3] = {
+    PB_FIELD(1, MESSAGE, OPTIONAL, STATIC, FIRST, grpc_lb_v0_LoadBalanceRequest,
+             initial_request, initial_request,
+             &grpc_lb_v0_InitialLoadBalanceRequest_fields),
+    PB_FIELD(2, MESSAGE, OPTIONAL, STATIC, OTHER, grpc_lb_v0_LoadBalanceRequest,
+             client_stats, initial_request, &grpc_lb_v0_ClientStats_fields),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2] = {
+    PB_FIELD(1, STRING, OPTIONAL, STATIC, FIRST,
+             grpc_lb_v0_InitialLoadBalanceRequest, name, name, 0),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_ClientStats_fields[4] = {
+    PB_FIELD(1, INT64, OPTIONAL, STATIC, FIRST, grpc_lb_v0_ClientStats,
+             total_requests, total_requests, 0),
+    PB_FIELD(2, INT64, OPTIONAL, STATIC, OTHER, grpc_lb_v0_ClientStats,
+             client_rpc_errors, total_requests, 0),
+    PB_FIELD(3, INT64, OPTIONAL, STATIC, OTHER, grpc_lb_v0_ClientStats,
+             dropped_requests, client_rpc_errors, 0),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3] = {
+    PB_FIELD(1, MESSAGE, OPTIONAL, STATIC, FIRST,
+             grpc_lb_v0_LoadBalanceResponse, initial_response, initial_response,
+             &grpc_lb_v0_InitialLoadBalanceResponse_fields),
+    PB_FIELD(2, MESSAGE, OPTIONAL, STATIC, OTHER,
+             grpc_lb_v0_LoadBalanceResponse, server_list, initial_response,
+             &grpc_lb_v0_ServerList_fields),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4] = {
+    PB_FIELD(1, STRING, OPTIONAL, STATIC, FIRST,
+             grpc_lb_v0_InitialLoadBalanceResponse, client_config,
+             client_config, 0),
+    PB_FIELD(2, STRING, OPTIONAL, STATIC, OTHER,
+             grpc_lb_v0_InitialLoadBalanceResponse, load_balancer_delegate,
+             client_config, 0),
+    PB_FIELD(3, MESSAGE, OPTIONAL, STATIC, OTHER,
+             grpc_lb_v0_InitialLoadBalanceResponse,
+             client_stats_report_interval, load_balancer_delegate,
+             &grpc_lb_v0_Duration_fields),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_ServerList_fields[3] = {
+    PB_FIELD(1, MESSAGE, REPEATED, CALLBACK, FIRST, grpc_lb_v0_ServerList,
+             servers, servers, &grpc_lb_v0_Server_fields),
+    PB_FIELD(3, MESSAGE, OPTIONAL, STATIC, OTHER, grpc_lb_v0_ServerList,
+             expiration_interval, servers, &grpc_lb_v0_Duration_fields),
+    PB_LAST_FIELD};
+
+const pb_field_t grpc_lb_v0_Server_fields[5] = {
+    PB_FIELD(1, STRING, OPTIONAL, STATIC, FIRST, grpc_lb_v0_Server, ip_address,
+             ip_address, 0),
+    PB_FIELD(2, INT32, OPTIONAL, STATIC, OTHER, grpc_lb_v0_Server, port,
+             ip_address, 0),
+    PB_FIELD(3, BYTES, OPTIONAL, STATIC, OTHER, grpc_lb_v0_Server,
+             load_balance_token, port, 0),
+    PB_FIELD(4, BOOL, OPTIONAL, STATIC, OTHER, grpc_lb_v0_Server, drop_request,
+             load_balance_token, 0),
+    PB_LAST_FIELD};
+
+/* Check that field information fits in pb_field_t */
+#if !defined(PB_FIELD_32BIT)
+/* If you get an error here, it means that you need to define PB_FIELD_32BIT
+ * compile-time option. You can do that in pb.h or on compiler command line.
+ *
+ * The reason you need to do this is that some of your messages contain tag
+ * numbers or field sizes that are larger than what can fit in 8 or 16 bit
+ * field descriptors.
+ */
+PB_STATIC_ASSERT(
+    (pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 65536 &&
+     pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 65536 &&
+     pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 65536 &&
+     pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 65536 &&
+     pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse,
+                   client_stats_report_interval) < 65536 &&
+     pb_membersize(grpc_lb_v0_ServerList, servers) < 65536 &&
+     pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 65536),
+    YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
+#endif
+
+#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT)
+/* If you get an error here, it means that you need to define PB_FIELD_16BIT
+ * compile-time option. You can do that in pb.h or on compiler command line.
+ *
+ * The reason you need to do this is that some of your messages contain tag
+ * numbers or field sizes that are larger than what can fit in the default
+ * 8 bit descriptors.
+ */
+PB_STATIC_ASSERT(
+    (pb_membersize(grpc_lb_v0_LoadBalanceRequest, initial_request) < 256 &&
+     pb_membersize(grpc_lb_v0_LoadBalanceRequest, client_stats) < 256 &&
+     pb_membersize(grpc_lb_v0_LoadBalanceResponse, initial_response) < 256 &&
+     pb_membersize(grpc_lb_v0_LoadBalanceResponse, server_list) < 256 &&
+     pb_membersize(grpc_lb_v0_InitialLoadBalanceResponse,
+                   client_stats_report_interval) < 256 &&
+     pb_membersize(grpc_lb_v0_ServerList, servers) < 256 &&
+     pb_membersize(grpc_lb_v0_ServerList, expiration_interval) < 256),
+    YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_grpc_lb_v0_Duration_grpc_lb_v0_LoadBalanceRequest_grpc_lb_v0_InitialLoadBalanceRequest_grpc_lb_v0_ClientStats_grpc_lb_v0_LoadBalanceResponse_grpc_lb_v0_InitialLoadBalanceResponse_grpc_lb_v0_ServerList_grpc_lb_v0_Server)
+#endif
diff --git a/src/core/proto/grpc/lb/v0/load_balancer.pb.h b/src/core/proto/grpc/lb/v0/load_balancer.pb.h
new file mode 100644
index 0000000..ac83665
--- /dev/null
+++ b/src/core/proto/grpc/lb/v0/load_balancer.pb.h
@@ -0,0 +1,221 @@
+/*
+ *
+ * Copyright 2016, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* Automatically generated nanopb header */
+/* Generated by nanopb-0.3.4-dev */
+
+#ifndef PB_LOAD_BALANCER_PB_H_INCLUDED
+#define PB_LOAD_BALANCER_PB_H_INCLUDED
+#include "third_party/nanopb/pb.h"
+#if PB_PROTO_HEADER_VERSION != 30
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enum definitions */
+/* Struct definitions */
+typedef struct _grpc_lb_v0_ClientStats {
+  bool has_total_requests;
+  int64_t total_requests;
+  bool has_client_rpc_errors;
+  int64_t client_rpc_errors;
+  bool has_dropped_requests;
+  int64_t dropped_requests;
+} grpc_lb_v0_ClientStats;
+
+typedef struct _grpc_lb_v0_Duration {
+  bool has_seconds;
+  int64_t seconds;
+  bool has_nanos;
+  int32_t nanos;
+} grpc_lb_v0_Duration;
+
+typedef struct _grpc_lb_v0_InitialLoadBalanceRequest {
+  bool has_name;
+  char name[128];
+} grpc_lb_v0_InitialLoadBalanceRequest;
+
+typedef PB_BYTES_ARRAY_T(64) grpc_lb_v0_Server_load_balance_token_t;
+typedef struct _grpc_lb_v0_Server {
+  bool has_ip_address;
+  char ip_address[46];
+  bool has_port;
+  int32_t port;
+  bool has_load_balance_token;
+  grpc_lb_v0_Server_load_balance_token_t load_balance_token;
+  bool has_drop_request;
+  bool drop_request;
+} grpc_lb_v0_Server;
+
+typedef struct _grpc_lb_v0_InitialLoadBalanceResponse {
+  bool has_client_config;
+  char client_config[64];
+  bool has_load_balancer_delegate;
+  char load_balancer_delegate[64];
+  bool has_client_stats_report_interval;
+  grpc_lb_v0_Duration client_stats_report_interval;
+} grpc_lb_v0_InitialLoadBalanceResponse;
+
+typedef struct _grpc_lb_v0_LoadBalanceRequest {
+  bool has_initial_request;
+  grpc_lb_v0_InitialLoadBalanceRequest initial_request;
+  bool has_client_stats;
+  grpc_lb_v0_ClientStats client_stats;
+} grpc_lb_v0_LoadBalanceRequest;
+
+typedef struct _grpc_lb_v0_ServerList {
+  pb_callback_t servers;
+  bool has_expiration_interval;
+  grpc_lb_v0_Duration expiration_interval;
+} grpc_lb_v0_ServerList;
+
+typedef struct _grpc_lb_v0_LoadBalanceResponse {
+  bool has_initial_response;
+  grpc_lb_v0_InitialLoadBalanceResponse initial_response;
+  bool has_server_list;
+  grpc_lb_v0_ServerList server_list;
+} grpc_lb_v0_LoadBalanceResponse;
+
+/* Default values for struct fields */
+
+/* Initializer values for message structs */
+#define grpc_lb_v0_Duration_init_default \
+  { false, 0, false, 0 }
+#define grpc_lb_v0_LoadBalanceRequest_init_default                   \
+  {                                                                  \
+    false, grpc_lb_v0_InitialLoadBalanceRequest_init_default, false, \
+        grpc_lb_v0_ClientStats_init_default                          \
+  }
+#define grpc_lb_v0_InitialLoadBalanceRequest_init_default \
+  { false, "" }
+#define grpc_lb_v0_ClientStats_init_default \
+  { false, 0, false, 0, false, 0 }
+#define grpc_lb_v0_LoadBalanceResponse_init_default                   \
+  {                                                                   \
+    false, grpc_lb_v0_InitialLoadBalanceResponse_init_default, false, \
+        grpc_lb_v0_ServerList_init_default                            \
+  }
+#define grpc_lb_v0_InitialLoadBalanceResponse_init_default \
+  { false, "", false, "", false, grpc_lb_v0_Duration_init_default }
+#define grpc_lb_v0_ServerList_init_default    \
+  {                                           \
+    {                                         \
+      { NULL }                                \
+      , NULL                                  \
+    }                                         \
+    , false, grpc_lb_v0_Duration_init_default \
+  }
+#define grpc_lb_v0_Server_init_default \
+  { false, "", false, 0, false, {0, {0}}, false, 0 }
+#define grpc_lb_v0_Duration_init_zero \
+  { false, 0, false, 0 }
+#define grpc_lb_v0_LoadBalanceRequest_init_zero                   \
+  {                                                               \
+    false, grpc_lb_v0_InitialLoadBalanceRequest_init_zero, false, \
+        grpc_lb_v0_ClientStats_init_zero                          \
+  }
+#define grpc_lb_v0_InitialLoadBalanceRequest_init_zero \
+  { false, "" }
+#define grpc_lb_v0_ClientStats_init_zero \
+  { false, 0, false, 0, false, 0 }
+#define grpc_lb_v0_LoadBalanceResponse_init_zero                   \
+  {                                                                \
+    false, grpc_lb_v0_InitialLoadBalanceResponse_init_zero, false, \
+        grpc_lb_v0_ServerList_init_zero                            \
+  }
+#define grpc_lb_v0_InitialLoadBalanceResponse_init_zero \
+  { false, "", false, "", false, grpc_lb_v0_Duration_init_zero }
+#define grpc_lb_v0_ServerList_init_zero    \
+  {                                        \
+    {                                      \
+      { NULL }                             \
+      , NULL                               \
+    }                                      \
+    , false, grpc_lb_v0_Duration_init_zero \
+  }
+#define grpc_lb_v0_Server_init_zero \
+  { false, "", false, 0, false, {0, {0}}, false, 0 }
+
+/* Field tags (for use in manual encoding/decoding) */
+#define grpc_lb_v0_ClientStats_total_requests_tag 1
+#define grpc_lb_v0_ClientStats_client_rpc_errors_tag 2
+#define grpc_lb_v0_ClientStats_dropped_requests_tag 3
+#define grpc_lb_v0_Duration_seconds_tag 1
+#define grpc_lb_v0_Duration_nanos_tag 2
+#define grpc_lb_v0_InitialLoadBalanceRequest_name_tag 1
+#define grpc_lb_v0_Server_ip_address_tag 1
+#define grpc_lb_v0_Server_port_tag 2
+#define grpc_lb_v0_Server_load_balance_token_tag 3
+#define grpc_lb_v0_Server_drop_request_tag 4
+#define grpc_lb_v0_InitialLoadBalanceResponse_client_config_tag 1
+#define grpc_lb_v0_InitialLoadBalanceResponse_load_balancer_delegate_tag 2
+#define grpc_lb_v0_InitialLoadBalanceResponse_client_stats_report_interval_tag 3
+#define grpc_lb_v0_LoadBalanceRequest_initial_request_tag 1
+#define grpc_lb_v0_LoadBalanceRequest_client_stats_tag 2
+#define grpc_lb_v0_ServerList_servers_tag 1
+#define grpc_lb_v0_ServerList_expiration_interval_tag 3
+#define grpc_lb_v0_LoadBalanceResponse_initial_response_tag 1
+#define grpc_lb_v0_LoadBalanceResponse_server_list_tag 2
+
+/* Struct field encoding specification for nanopb */
+extern const pb_field_t grpc_lb_v0_Duration_fields[3];
+extern const pb_field_t grpc_lb_v0_LoadBalanceRequest_fields[3];
+extern const pb_field_t grpc_lb_v0_InitialLoadBalanceRequest_fields[2];
+extern const pb_field_t grpc_lb_v0_ClientStats_fields[4];
+extern const pb_field_t grpc_lb_v0_LoadBalanceResponse_fields[3];
+extern const pb_field_t grpc_lb_v0_InitialLoadBalanceResponse_fields[4];
+extern const pb_field_t grpc_lb_v0_ServerList_fields[3];
+extern const pb_field_t grpc_lb_v0_Server_fields[5];
+
+/* Maximum encoded size of messages (where known) */
+#define grpc_lb_v0_Duration_size 22
+#define grpc_lb_v0_LoadBalanceRequest_size 169
+#define grpc_lb_v0_InitialLoadBalanceRequest_size 131
+#define grpc_lb_v0_ClientStats_size 33
+#define grpc_lb_v0_InitialLoadBalanceResponse_size 156
+#define grpc_lb_v0_Server_size 127
+
+/* Message IDs (where set with "msgid" option) */
+#ifdef PB_MSGID
+
+#define LOAD_BALANCER_MESSAGES
+
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/src/proto/grpc/lb/v0/load_balancer.options b/src/proto/grpc/lb/v0/load_balancer.options
new file mode 100644
index 0000000..6d4528f
--- /dev/null
+++ b/src/proto/grpc/lb/v0/load_balancer.options
@@ -0,0 +1,6 @@
+grpc.lb.v0.InitialLoadBalanceRequest.name max_size:128
+grpc.lb.v0.InitialLoadBalanceResponse.client_config max_size:64
+grpc.lb.v0.InitialLoadBalanceResponse.load_balancer_delegate max_size:64
+grpc.lb.v0.Server.ip_address max_size:46
+grpc.lb.v0.Server.load_balance_token max_size:64
+load_balancer.proto no_unions:true
diff --git a/src/proto/grpc/lb/v0/load_balancer.proto b/src/proto/grpc/lb/v0/load_balancer.proto
new file mode 100644
index 0000000..e88a4f8
--- /dev/null
+++ b/src/proto/grpc/lb/v0/load_balancer.proto
@@ -0,0 +1,144 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package grpc.lb.v0;
+
+message Duration {
+
+  // Signed seconds of the span of time. Must be from -315,576,000,000
+  // to +315,576,000,000 inclusive.
+  int64 seconds = 1;
+
+  // Signed fractions of a second at nanosecond resolution of the span
+  // of time. Durations less than one second are represented with a 0
+  // `seconds` field and a positive or negative `nanos` field. For durations
+  // of one second or more, a non-zero value for the `nanos` field must be
+  // of the same sign as the `seconds` field. Must be from -999,999,999
+  // to +999,999,999 inclusive.
+  int32 nanos = 2;
+}
+
+service LoadBalancer {
+  // Bidirectional rpc to get a list of servers.
+  rpc BalanceLoad(stream LoadBalanceRequest)
+      returns (stream LoadBalanceResponse);
+}
+
+message LoadBalanceRequest {
+  oneof load_balance_request_type {
+    // This message should be sent on the first request to the load balancer.
+    InitialLoadBalanceRequest initial_request = 1;
+
+    // The client stats should be periodically reported to the load balancer
+    // based on the duration defined in the InitialLoadBalanceResponse.
+    ClientStats client_stats = 2;
+  }
+}
+
+message InitialLoadBalanceRequest {
+  // Name of load balanced service (IE, service.grpc.gslb.google.com)
+  string name = 1;
+}
+
+// Contains client level statistics that are useful to load balancing. Each
+// count should be reset to zero after reporting the stats.
+message ClientStats {
+  // The total number of requests sent by the client since the last report.
+  int64 total_requests = 1;
+
+  // The number of client rpc errors since the last report.
+  int64 client_rpc_errors = 2;
+
+  // The number of dropped requests since the last report.
+  int64 dropped_requests = 3;
+}
+
+message LoadBalanceResponse {
+  oneof load_balance_response_type {
+    // This message should be sent on the first response to the client.
+    InitialLoadBalanceResponse initial_response = 1;
+
+    // Contains the list of servers selected by the load balancer. The client
+    // should send requests to these servers in the specified order.
+    ServerList server_list = 2;
+  }
+}
+
+message InitialLoadBalanceResponse {
+  oneof initial_response_type {
+    // Contains gRPC config options like RPC deadline or flow control.
+    // TODO(yetianx): Change to ClientConfig after it is defined.
+    string client_config = 1;
+
+    // This is an application layer redirect that indicates the client should
+    // use the specified server for load balancing. When this field is set in
+    // the response, the client should open a separate connection to the
+    // load_balancer_delegate and call the BalanceLoad method.
+    string load_balancer_delegate = 2;
+  }
+
+  // This interval defines how often the client should send the client stats
+  // to the load balancer. Stats should only be reported when the duration is
+  // positive.
+  Duration client_stats_report_interval = 3;
+}
+
+message ServerList {
+  // Contains a list of servers selected by the load balancer. The list will
+  // be updated when server resolutions change or as needed to balance load
+  // across more servers. The client should consume the server list in order
+  // unless instructed otherwise via the client_config.
+  repeated Server servers = 1;
+
+  // Indicates the amount of time that the client should consider this server
+  // list as valid. It may be considered stale after waiting this interval of
+  // time after receiving the list. If the interval is not positive, the
+  // client can assume the list is valid until the next list is received.
+  Duration expiration_interval = 3;
+}
+
+message Server {
+  // A resolved address and port for the server. The IP address string may
+  // either be an IPv4 or IPv6 address.
+  string ip_address = 1;
+  int32 port = 2;
+
+  // An opaque token that is passed from the client to the server in metadata.
+  // The server may expect this token to indicate that the request from the
+  // client was load balanced.
+  // TODO(yetianx): Not used right now, and will be used after implementing
+  // load report.
+  bytes load_balance_token = 3;
+
+  // Indicates whether this particular request should be dropped by the client
+  // when this server is chosen from the list.
+  bool drop_request = 4;
+}
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 8e90f7a..60af862 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -109,6 +109,7 @@
   'src/core/client_config/connector.c',
   'src/core/client_config/default_initial_connect_string.c',
   'src/core/client_config/initial_connect_string.c',
+  'src/core/client_config/lb_policies/load_balancer_api.c',
   'src/core/client_config/lb_policies/pick_first.c',
   'src/core/client_config/lb_policies/round_robin.c',
   'src/core/client_config/lb_policy.c',
@@ -172,6 +173,7 @@
   'src/core/json/json_reader.c',
   'src/core/json/json_string.c',
   'src/core/json/json_writer.c',
+  'src/core/proto/grpc/lb/v0/load_balancer.pb.c',
   'src/core/surface/alarm.c',
   'src/core/surface/api_trace.c',
   'src/core/surface/byte_buffer.c',
@@ -226,6 +228,9 @@
   'src/core/census/operation.c',
   'src/core/census/placeholders.c',
   'src/core/census/tracing.c',
+  'third_party/nanopb/pb_common.c',
+  'third_party/nanopb/pb_decode.c',
+  'third_party/nanopb/pb_encode.c',
   'src/boringssl/err_data.c',
   'third_party/boringssl/crypto/aes/aes.c',
   'third_party/boringssl/crypto/aes/mode_wrappers.c',