diff --git a/proto/bmp/bmp.c b/proto/bmp/bmp.c
index 9889522a..5f41747f 100644
--- a/proto/bmp/bmp.c
+++ b/proto/bmp/bmp.c
@@ -171,6 +171,8 @@ enum bmp_term_reason {
 
 #define IP4_MAX_TTL 255
 
+// This value is passing to socket error handler to force restart socket
+#define FORCE_SOCKET_ERROR 0
 
 #define IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(expr, msg, rv...)     \
   do {                                                                      \
@@ -187,11 +189,22 @@ enum bmp_term_reason {
     IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(!(p), msg, rv);	\
   } while (0)
 
+static void
+bmp_setup_socket(struct bmp_proto *p);
+
+static void
+bmp_connect(struct bmp_proto *p);
+
+static void
+bmp_close_conn(struct bmp_proto *p);
 
 // Handle BIRD socket error event
 static void
 bmp_sock_err(sock *sk, int err);
 
+static void
+bmp_station_connected(struct birdsock *sk);
+
 static void
 bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp,
   const byte* tx_data, const size_t tx_data_size,
@@ -250,7 +263,11 @@ bmp_init_msg_serialize(buffer *stream, const char *sys_descr, const char *sys_na
 static void
 bmp_schedule_tx_packet(struct bmp_proto *p, const byte *payload, const size_t size)
 {
-  ASSERT(p->station_connected);
+  if (!p->sk || (p->p.proto_state != PS_UP))
+  {
+    bmp_sock_err(p->sk, FORCE_SOCKET_ERROR);
+    return;
+  }
 
   struct bmp_data_node *tx_data = mb_alloc(p->tx_mem_pool, sizeof (struct bmp_data_node));
   tx_data->data = mb_alloc(p->tx_mem_pool, size);
@@ -272,26 +289,29 @@ bmp_schedule_tx_packet(struct bmp_proto *p, const byte *payload, const size_t si
 static void
 bmp_startup(struct bmp_proto *p)
 {
-  ASSERT(p->station_connected && !p->started);
-
   buffer payload = bmp_buffer_alloc(p->buffer_mpool, DEFAULT_MEM_BLOCK_SIZE);
   bmp_init_msg_serialize(&payload, p->sys_descr, p->sys_name);
   bmp_schedule_tx_packet(p, bmp_buffer_data(&payload), bmp_buffer_pos(&payload));
   bmp_buffer_free(&payload);
-
-  p->started = true;
 }
 
 static void
 bmp_fire_tx(void *p_)
 {
   struct bmp_proto *p = p_;
+  if (!p->sk || (p->p.proto_state != PS_UP))
+  {
+    bmp_sock_err(p->sk, FORCE_SOCKET_ERROR);
+    return;
+  }
+
   byte *buf = p->sk->tbuf;
   IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
     EMPTY_LIST(p->tx_queue),
     "Called BMP TX event handler when there is not any data to send"
   );
 
+  int rv;
   size_t cnt = 0; // Counts max packets which we want to send per TX slot
   struct bmp_data_node *tx_data;
   struct bmp_data_node *tx_data_next;
@@ -304,14 +324,18 @@ bmp_fire_tx(void *p_)
 
     size_t data_size = tx_data->data_size;
     memcpy(buf, tx_data->data, tx_data->data_size);
-    mb_free(tx_data->data);
-    rem_node((node *) tx_data);
-    mb_free(tx_data);
+    rv = sk_send(p->sk, data_size);
     IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
-      (sk_send(p->sk, data_size) <= 0),
+      (rv < 0),
       "Failed to send BMP packet"
     );
 
+    mb_free(tx_data->data);
+    rem_node((node *) tx_data);
+    mb_free(tx_data);
+    if (rv == 0)
+      return;
+
     // BMP packets should be treat with lowest priority when scheduling sending
     // packets to target. That's why we want to send max. 32 packets per event
     // call
@@ -333,13 +357,13 @@ bmp_tx(struct birdsock *sk)
   bmp_fire_tx(sk->data);
 }
 
+// Configure socket with dynamic values, then open it
 static inline int
 bmp_open_socket(struct bmp_proto *p)
 {
   sock *s = p->sk;
   s->daddr = p->station_ip;
   s->dport = p->station_port;
-  s->err_hook = bmp_sock_err;
 
   int rc = sk_open(s);
 
@@ -349,26 +373,48 @@ bmp_open_socket(struct bmp_proto *p)
   return rc;
 }
 
+void
+bmp_close_conn(struct bmp_proto *p)
+{
+  rfree(p->connect_retry_timer);
+  p->connect_retry_timer = NULL;
+  rfree(p->tx_ev);
+  p->tx_ev = NULL;
+  rfree(p->sk);
+  p->sk = NULL;
+}
+
 static void
 bmp_connection_retry(timer *t)
 {
   struct bmp_proto *p = t->data;
+  tm_stop(t);
 
-  if (bmp_open_socket(p) < 0)
+  if (p->p.proto_state == PS_START)
   {
-    log(L_DEBUG "Failed to connect to BMP station");
-    return;
+    bmp_close_conn(p);
+    bmp_setup_socket(p);
+    bmp_connect(p);
   }
-
-  log(L_DEBUG "Connected to BMP station after connection retry");
-  tm_stop(t);
 }
 
 void
 bmp_sock_err(sock *sk, int err)
 {
-  struct bmp_proto *p = sk->data;
-  log(L_WARN "[BMP:%s] Socket error: %M", p->p.name, err);
+  struct bmp_proto *p = sk ? sk->data : g_bmp;
+
+  if ((p->p.proto_state == PS_UP) || (p->p.proto_state == PS_DOWN))
+    proto_notify_state(&p->p, PS_START);
+
+  // Check if err_hook has not been called synchronously from sk_send() or other bmp_*() code
+  if (err != 0 && p->sk)
+  {
+    rfree(p->sk);
+    p->sk = NULL;
+  }
+
+  if (!tm_active(p->connect_retry_timer))
+    tm_start(p->connect_retry_timer, CONNECT_RETRY_SEC);
 }
 
 static inline void
@@ -489,6 +535,20 @@ bmp_peer_down_notif_msg_serialize(buffer *stream, const bool is_peer_global,
   bmp_put_data(stream, data, data_size);
 }
 
+void
+bmp_connect(struct bmp_proto *p)
+{
+  p->tx_ev = ev_new_init(p->tx_mem_pool, bmp_fire_tx, p);
+
+  init_list(&p->tx_queue);
+  init_list(&p->rt_table_in_pre_policy.update_msg_queue);
+  p->connect_retry_timer = tm_new_init(p->p.pool, bmp_connection_retry, p,
+                                 CONNECT_RETRY_SEC, 0 /* not randomized */);
+  bmp_open_socket(p);
+
+  tm_start(p->connect_retry_timer, CONNECT_RETRY_SEC);
+}
+
 /**
  * bmp_open - initialize internal resources of BMP implementation.
  * NOTE: It does not connect to BMP collector yet.
@@ -504,29 +564,10 @@ bmp_open(const struct proto *P)
   p->map_mem_pool = rp_new(P->pool, "BMP Map");
   p->tx_mem_pool = rp_new(P->pool, "BMP Tx");
   p->update_msg_mem_pool = rp_new(P->pool, "BMP Update");
-  p->tx_ev = ev_new_init(p->tx_mem_pool, bmp_fire_tx, p);
 
   bmp_peer_map_init(&p->peer_open_msg.tx_msg, p->map_mem_pool);
   bmp_peer_map_init(&p->peer_open_msg.rx_msg, p->map_mem_pool);
   bmp_peer_map_init(&p->bgp_peers, p->map_mem_pool);
-
-  init_list(&p->tx_queue);
-  init_list(&p->rt_table_in_pre_policy.update_msg_queue);
-  p->station_connected = false;
-  p->started = false;
-  p->connect_retry_timer = NULL;
-  if (bmp_open_socket(p) < 0)
-  {
-    log(L_DEBUG "Failed to connect to BMP station");
-    p->connect_retry_timer = tm_new_init(P->pool, bmp_connection_retry, p,
-                                   CONNECT_RETRY_SEC, 0 /* not randomized */);
-    tm_start(p->connect_retry_timer, CONNECT_RETRY_SEC);
-    p->station_connected = false;
-  }
-  else
-  {
-    log(L_DEBUG "Connected to BMP station");
-  }
 }
 
 void
@@ -535,7 +576,6 @@ bmp_peer_map_walk_tx_open_msg_and_send_peer_up_notif(
   const size_t tx_msg_size, void *bmp_)
 {
   struct bmp_proto *p = bmp_;
-  ASSERT(p->station_connected);
 
   const struct bmp_peer_map_entry *map_rx_msg = bmp_peer_map_get(&p->peer_open_msg.rx_msg, key);
   IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
@@ -551,11 +591,8 @@ bmp_peer_map_walk_tx_open_msg_and_send_peer_up_notif(
 
   const struct bgp_proto *bgp;
   memcpy(&bgp, map_bgp_proto->data.buf, sizeof (bgp));
-  if (bgp->p.proto_state == PS_UP)
-  {
-    bmp_send_peer_up_notif_msg(p, bgp, tx_msg, tx_msg_size,
-			       map_rx_msg->data.buf, map_rx_msg->data.buf_size);
-  }
+  bmp_send_peer_up_notif_msg(p, bgp, tx_msg, tx_msg_size,
+		       map_rx_msg->data.buf, map_rx_msg->data.buf_size);
 }
 
 static void
@@ -647,7 +684,11 @@ bmp_send_peer_up_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp,
   const byte* tx_data, const size_t tx_data_size,
   const byte* rx_data, const size_t rx_data_size)
 {
-  ASSERT(p->station_connected);
+  if (!p->sk)
+  {
+    bmp_sock_err(p->sk, FORCE_SOCKET_ERROR);
+    return;
+  }
 
   const struct birdsock *sk = bmp_get_birdsock_ext(bgp);
   IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
@@ -680,22 +721,22 @@ bmp_put_sent_bgp_open_msg(const struct bgp_proto *bgp, const byte* pkt,
 
   struct bmp_peer_map_key key = bmp_peer_map_key_create(bgp->remote_ip,
                                   bgp->remote_as);
-  const struct bmp_peer_map_entry *map_entry
+  const struct bmp_peer_map_entry *tx_map_entry
+    = bmp_peer_map_get(&p->peer_open_msg.tx_msg, key);
+  const struct bmp_peer_map_entry *rx_map_entry
     = bmp_peer_map_get(&p->peer_open_msg.rx_msg, key);
-  if (!map_entry || !p->started)
-  {
+  if (!tx_map_entry)
     bmp_peer_map_insert(&p->peer_open_msg.tx_msg, key, pkt, pkt_size);
 
-    if (!map_entry)
-    {
-      bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp));
-    }
-
+  if (!tx_map_entry && !rx_map_entry)
+  {
+    bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp));
+    // There is still missing TX or RX OPEN MSG
     return;
   }
 
-  bmp_send_peer_up_notif_msg(p, bgp, pkt, pkt_size, map_entry->data.buf,
-			     map_entry->data.buf_size);
+  bmp_send_peer_up_notif_msg(p, bgp, pkt, pkt_size, rx_map_entry->data.buf,
+			     rx_map_entry->data.buf_size);
 }
 
 void
@@ -711,21 +752,21 @@ bmp_put_recv_bgp_open_msg(const struct bgp_proto *bgp, const byte* pkt,
 
   struct bmp_peer_map_key key
     = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as);
-  const struct bmp_peer_map_entry *map_data
+  const struct bmp_peer_map_entry *tx_map_entry
     = bmp_peer_map_get(&p->peer_open_msg.tx_msg, key);
-  if (!map_data || !p->started)
-  {
+  const struct bmp_peer_map_entry *rx_map_entry
+    = bmp_peer_map_get(&p->peer_open_msg.rx_msg, key);
+  if (!rx_map_entry)
     bmp_peer_map_insert(&p->peer_open_msg.rx_msg, key, pkt, pkt_size);
 
-    if (!map_data)
-    {
-      bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp));
-    }
-
+  if (!tx_map_entry && !rx_map_entry)
+  {
+    bmp_peer_map_insert(&p->bgp_peers, key, (const byte *) &bgp, sizeof (bgp));
+    // There is still missing TX or RX OPEN MSG
     return;
   }
 
-  bmp_send_peer_up_notif_msg(p, bgp, map_data->data.buf, map_data->data.buf_size,
+  bmp_send_peer_up_notif_msg(p, bgp, tx_map_entry->data.buf, tx_map_entry->data.buf_size,
 			     pkt, pkt_size);
 }
 
@@ -744,10 +785,8 @@ bmp_route_monitor_update_in_pre_begin()
     return;
   }
 
-  IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
-    !p->started,
-    "BMP instance not started yet"
-  );
+  if (p->p.proto_state != PS_UP)
+    return;
 
   IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
     !EMPTY_LIST(p->rt_table_in_pre_policy.update_msg_queue),
@@ -775,15 +814,8 @@ bmp_route_monitor_put_update_in_pre_msg(const byte *data, const size_t data_size
     return;
   }
 
-  IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
-    !p->started,
-    "BMP instance not started yet"
-  );
-
-  IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
-    !p->rt_table_in_pre_policy.update_in_progress,
-    "BMP route monitoring update not started yet"
-  );
+  if (!p->rt_table_in_pre_policy.update_in_progress)
+    return;
 
   struct bmp_data_node *upd_msg = mb_alloc(p->update_msg_mem_pool,
                                sizeof (struct bmp_data_node));
@@ -809,11 +841,6 @@ bmp_route_monitor_update_in_pre_commit(const struct bgp_proto *bgp)
     return;
   }
 
-  IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
-    (!p->started || EMPTY_LIST(p->rt_table_in_pre_policy.update_msg_queue)),
-    "BMP route monitoring update not started yet"
-  );
-
   const struct birdsock *sk = bmp_get_birdsock(bgp);
   IF_PTR_IS_NULL_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
     sk,
@@ -871,10 +898,8 @@ bmp_route_monitor_update_in_pre_end()
     return;
   }
 
-  IF_COND_TRUE_PRINT_ERR_MSG_AND_RETURN_OPT_VAL(
-    (!p->started || EMPTY_LIST(p->rt_table_in_pre_policy.update_msg_queue)),
-    "BMP route monitoring update not started yet"
-  );
+  if (EMPTY_LIST(p->rt_table_in_pre_policy.update_msg_queue))
+    return;
 
   struct bmp_data_node *upd_msg;
   struct bmp_data_node *upd_msg_next;
@@ -890,6 +915,8 @@ static void
 bmp_route_monitor_pre_policy_table_in_snapshot(struct channel *C)
 {
   struct bmp_proto *p = g_bmp;
+  if (!p)
+    return;
 
   if (p->monitoring_rib.in_pre_policy == false)
   {
@@ -950,8 +977,6 @@ static void
 bmp_send_peer_down_notif_msg(struct bmp_proto *p, const struct bgp_proto *bgp,
   const byte* data, const size_t data_size)
 {
-  ASSERT(p->station_connected);
-
   const struct bgp_caps *remote_caps = bmp_get_bgp_remote_caps_ext(bgp);
   bool is_global_instance_peer = bmp_is_peer_global_instance(bgp);
   buffer payload
@@ -970,18 +995,13 @@ bmp_peer_down(const struct bgp_proto *bgp, const int err_class, const byte *pkt,
   size_t pkt_size)
 {
   struct bmp_proto *p = g_bmp;
-
-  if (!p || !p->started)
-  {
+  if (!p)
     return;
-  }
 
   struct bmp_peer_map_key key
     = bmp_peer_map_key_create(bgp->remote_ip, bgp->remote_as);
   if (!bmp_peer_map_get(&p->bgp_peers, key))
-  {
     return;
-  }
 
   bmp_peer_map_remove(&p->peer_open_msg.tx_msg, key);
   bmp_peer_map_remove(&p->peer_open_msg.rx_msg, key);
@@ -1034,6 +1054,12 @@ static void
 bmp_send_termination_msg(struct bmp_proto *p,
   const enum bmp_term_reason reason)
 {
+  if (!p->sk)
+  {
+    bmp_sock_err(p->sk, FORCE_SOCKET_ERROR);
+    return;
+  }
+
   const size_t term_msg_hdr_size = BMP_TERM_INFO_TYPE_SIZE
                                      + BMP_TERM_INFO_LEN_FIELD_SIZE
                                      + BMP_TERM_REASON_CODE_SIZE;
@@ -1052,23 +1078,22 @@ bmp_send_termination_msg(struct bmp_proto *p,
   bmp_buffer_free(&stream);
 }
 
-static void
+void
 bmp_station_connected(struct birdsock *sk)
 {
   struct bmp_proto *p = (void *) sk->data;
 
   sk->tx_hook = bmp_tx;
-  p->station_connected = true;
 
+  proto_notify_state(&p->p, PS_UP);
   bmp_startup(p);
 
   bmp_peer_map_walk(&p->peer_open_msg.tx_msg,
 		    bmp_peer_map_walk_tx_open_msg_and_send_peer_up_notif, p);
-  bmp_peer_map_flush(&p->peer_open_msg.tx_msg);
-  bmp_peer_map_flush(&p->peer_open_msg.rx_msg);
 }
 
-static inline void
+// Configure socket only with static values
+void
 bmp_setup_socket(struct bmp_proto *p)
 {
   sock *sk = sk_new(p->tx_mem_pool);
@@ -1076,6 +1101,8 @@ bmp_setup_socket(struct bmp_proto *p)
   sk->ttl = IP4_MAX_TTL;
   sk->tos = IP_PREC_INTERNET_CONTROL;
   sk->tbsize = BGP_TX_BUFFER_EXT_SIZE;
+  sk->tos = IP_PREC_INTERNET_CONTROL;
+  sk->err_hook = bmp_sock_err;
   sk->tx_hook = bmp_station_connected;
 
   p->sk = sk;
@@ -1089,7 +1116,7 @@ bmp_init(struct proto_config *CF)
   struct proto *P = proto_new(CF);
   struct bmp_proto *p = (void *) P;
   struct bmp_config *cf = (void *) CF;
-
+  g_bmp = p; // FIXME: When multiple instances of BMP will be needed
   p->cf = cf;
   p->station_ip = cf->station_ip;
   p->station_port = cf->station_port;
@@ -1099,6 +1126,7 @@ bmp_init(struct proto_config *CF)
   p->monitoring_rib.in_post_policy = cf->monitoring_rib_in_post_policy;
   p->monitoring_rib.local = cf->monitoring_rib_local;
 
+  bmp_open(P);
   return P;
 }
 
@@ -1108,11 +1136,9 @@ bmp_start(struct proto *P)
   struct bmp_proto *p = (void *) P;
 
   bmp_setup_socket(p);
-  bmp_open(P);
-
-  g_bmp = p;
+  bmp_connect(p);
 
-  return PS_UP;
+  return PS_START;
 }
 
 static int
@@ -1121,19 +1147,16 @@ bmp_shutdown(struct proto *P)
   struct bmp_proto *p = (void *) P;
   bmp_send_termination_msg(p, BMP_TERM_REASON_ADM);
 
-  p->station_connected = false;
-  p->started = false;
-
   g_bmp = NULL;
 
   return PS_DOWN;
 }
 
 static int
-bmp_reconfigure(struct proto *P UNUSED, struct proto_config *CF UNUSED)
+bmp_reconfigure(struct proto *P, struct proto_config *CF UNUSED)
 {
   log(L_WARN "Reconfiguring BMP is not supported");
-  return PS_UP;
+  return P->proto_state;
 }
 
 struct protocol proto_bmp = {
diff --git a/proto/bmp/bmp.h b/proto/bmp/bmp.h
index a43827b3..df5f0d99 100644
--- a/proto/bmp/bmp.h
+++ b/proto/bmp/bmp.h
@@ -81,8 +81,6 @@ struct bmp_proto {
   list tx_queue;                   // Stores queued packets going to be sent
   timer *connect_retry_timer;      // Timer for retrying connection to the BMP collector
   struct rt_table_info rt_table_in_pre_policy; // Pre-policy route import table 
-  bool station_connected;          // Flag that stores connection status with BMP station
-  bool started;                    // Flag that stores running status of BMP instance
 };
 
 /**
