diff --git a/daemon/core/emane/linkmonitor.py b/daemon/core/emane/linkmonitor.py
index 6d4daa8d..e161ada2 100644
--- a/daemon/core/emane/linkmonitor.py
+++ b/daemon/core/emane/linkmonitor.py
@@ -19,7 +19,6 @@ except ImportError:
     except ImportError:
         logging.debug("compatible emane python bindings not installed")
 
-
 if TYPE_CHECKING:
     from core.emane.emanemanager import EmaneManager
 
@@ -59,9 +58,11 @@ class EmaneLink:
         self.to_nem = to_nem
         self.sinr = sinr
         self.last_seen = None
+        self.updated = False
         self.touch()
 
     def update(self, sinr: float) -> None:
+        self.updated = self.sinr != sinr
         self.sinr = sinr
         self.touch()
 
@@ -234,19 +235,23 @@ class EmaneLinkMonitor:
         current_links = set(self.links.keys())
         new_links = current_links - previous_links
 
-        # find dead links
+        # find updated and dead links
         dead_links = []
         for link_id, link in self.links.items():
+            complete_id = self.get_complete_id(link_id)
             if link.is_dead(self.link_timeout):
                 dead_links.append(link_id)
+            elif link.updated and complete_id in self.complete_links:
+                link.updated = False
+                self.send_link(MessageFlags.NONE, complete_id)
 
         # announce dead links
         for link_id in dead_links:
-            del self.links[link_id]
             complete_id = self.get_complete_id(link_id)
             if complete_id in self.complete_links:
                 self.complete_links.remove(complete_id)
                 self.send_link(MessageFlags.DELETE, complete_id)
+            del self.links[link_id]
 
         # announce new links
         for link_id in new_links:
@@ -271,6 +276,13 @@ class EmaneLinkMonitor:
         reverse_id = link_id[1], link_id[0]
         return link_id in self.links and reverse_id in self.links
 
+    def get_link_label(self, link_id: Tuple[int, int]) -> str:
+        source_id = tuple(sorted(link_id))
+        source_link = self.links[source_id]
+        dest_id = link_id[::-1]
+        dest_link = self.links[dest_id]
+        return f"{source_link.sinr:.1f} / {dest_link.sinr:.1f}"
+
     def send_link(self, message_type: MessageFlags, link_id: Tuple[int, int]) -> None:
         nem_one, nem_two = link_id
         emane_one, netif = self.emane_manager.nemlookup(nem_one)
@@ -291,11 +303,20 @@ class EmaneLinkMonitor:
             node_two.name,
             nem_two,
         )
-        self.send_message(message_type, node_one.id, node_two.id, emane_one.id)
+        label = self.get_link_label(link_id)
+        self.send_message(message_type, label, node_one.id, node_two.id, emane_one.id)
 
-    def send_message(self, message_type, node_one, node_two, emane_id) -> None:
+    def send_message(
+        self,
+        message_type: MessageFlags,
+        label: str,
+        node_one: int,
+        node_two: int,
+        emane_id: int,
+    ) -> None:
         link_data = LinkData(
             message_type=message_type,
+            label=label,
             node1_id=node_one,
             node2_id=node_two,
             network_id=emane_id,
diff --git a/daemon/core/emulator/data.py b/daemon/core/emulator/data.py
index 26082f94..a7d4c9df 100644
--- a/daemon/core/emulator/data.py
+++ b/daemon/core/emulator/data.py
@@ -96,6 +96,7 @@ class NodeData:
 @dataclass
 class LinkData:
     message_type: MessageFlags = None
+    label: str = None
     node1_id: int = None
     node2_id: int = None
     delay: float = None
diff --git a/daemon/core/plugins/sdt.py b/daemon/core/plugins/sdt.py
index edfde932..befbf340 100644
--- a/daemon/core/plugins/sdt.py
+++ b/daemon/core/plugins/sdt.py
@@ -350,6 +350,7 @@ class Sdt:
         node_one: int,
         node_two: int,
         network_id: int = None,
+        label: str = None,
         is_wireless: bool = False,
     ) -> None:
         """
@@ -358,10 +359,11 @@ class Sdt:
         :param node_one: node one id
         :param node_two: node two id
         :param network_id: network link is associated with, None otherwise
+        :param label: label for link
         :param is_wireless: True if link is wireless, False otherwise
         :return: nothing
         """
-        logging.debug("sdt add link: %s, %s, %s", node_one, node_two, is_wireless)
+        logging.debug("sdt add link: %s, %s, %s", node_one, node_two, network_id)
         if not self.connect():
             return
         if self.wireless_net_check(node_one) or self.wireless_net_check(node_two):
@@ -376,18 +378,24 @@ class Sdt:
             node = self.session.nodes[network_id]
             network_name = node.name
             layer = f"{layer}::{network_name}"
-        self.cmd(f"link {node_one},{node_two},{link_id} linkLayer {layer} line {attr}")
+        link_label = ""
+        if label:
+            link_label = f'linklabel on,"{label}"'
+        self.cmd(
+            f"link {node_one},{node_two},{link_id} linkLayer {layer} line {attr} "
+            f"{link_label}"
+        )
 
     def delete_link(self, node_one: int, node_two: int, network_id: int = None) -> None:
         """
-        Handle deleting a node in SDT.
+        Handle deleting a link in SDT.
 
         :param node_one: node one id
         :param node_two: node two id
         :param network_id: network link is associated with, None otherwise
         :return: nothing
         """
-        logging.debug("sdt delete link: %s, %s", node_one, node_two)
+        logging.debug("sdt delete link: %s, %s, %s", node_one, node_two, network_id)
         if not self.connect():
             return
         if self.wireless_net_check(node_one) or self.wireless_net_check(node_two):
@@ -395,6 +403,27 @@ class Sdt:
         link_id = get_link_id(node_one, node_two, network_id)
         self.cmd(f"delete link,{node_one},{node_two},{link_id}")
 
+    def edit_link(
+        self, node_one: int, node_two: int, network_id: int, label: str
+    ) -> None:
+        """
+        Handle editing a link in SDT.
+
+        :param node_one: node one id
+        :param node_two: node two id
+        :param network_id: network link is associated with, None otherwise
+        :param label: label to update
+        :return: nothing
+        """
+        logging.debug("sdt edit link: %s, %s, %s", node_one, node_two, network_id)
+        if not self.connect():
+            return
+        if self.wireless_net_check(node_one) or self.wireless_net_check(node_two):
+            return
+        link_id = get_link_id(node_one, node_two, network_id)
+        link_label = f'linklabel on,"{label}"'
+        self.cmd(f"link {node_one},{node_two},{link_id} {link_label}")
+
     def handle_link_update(self, link_data: LinkData) -> None:
         """
         Handle link broadcast messages and push changes to SDT.
@@ -406,7 +435,10 @@ class Sdt:
         node_two = link_data.node2_id
         network_id = link_data.network_id
         is_wireless = link_data.link_type == LinkTypes.WIRELESS
+        label = link_data.label
         if link_data.message_type == MessageFlags.ADD:
-            self.add_link(node_one, node_two, network_id, is_wireless)
+            self.add_link(node_one, node_two, network_id, label, is_wireless)
         elif link_data.message_type == MessageFlags.DELETE:
             self.delete_link(node_one, node_two, network_id)
+        elif link_data.message_type == MessageFlags.NONE and label:
+            self.edit_link(node_one, node_two, network_id, label)