From bed448b17786c97b210e761c6c9d122421a1a5f0 Mon Sep 17 00:00:00 2001
From: "guozhongfeng.gzf" <guozhongfeng.gzf@alibaba-inc.com>
Date: Sat, 7 Dec 2024 11:33:31 +0800
Subject: [PATCH] pathd: pathd support IPv6 address SID list

command:

router2(config-sr-te)# segment-list test_srv6
router2(config-sr-te-segment-list)# index 10 ipv6-address
  X:X::X:X  IPv6 address
router2(config-sr-te-segment-list)# index 10 ipv6-address 100:1::1
router2(config-sr-te-segment-list)# index 20 ipv6-address 200:1::1
router2(config-sr-te-segment-list)# index 30 mpls label
  (16-1048575)  Label Value
router2(config-sr-te-segment-list)# index 30 mpls label 100
% Configuration failed.

Error type: validation
Error description: The Segment List(test_srv6) Type must be SRv6!
router2(config-sr-te-segment-list)#
router2(config-sr-te)# segment-list test_mpls
router2(config-sr-te-segment-list)# index 10 mpls label 100
router2(config-sr-te-segment-list)# index 20 mpls label 200
router2(config-sr-te-segment-list)# index 30 ipv6-address 1:1::1
% Configuration failed.

Error type: validation
Error description: The Segment List(test_mpls) Type must be MPLS!
router2(config-sr-te-segment-list)#

router2# configure
router2(config)# seg
router2(config-sr)# traffic-eng
router2(config-sr-te)# policy color 100 endpoint
  A.B.C.D   SR Policy endpoint IPv4 address
  X:X::X:X  SR Policy endpoint IPv6 address
router2(config-sr-te)# policy color 100 endpoint 1.1.1.1
  <cr>
router2(config-sr-te)# policy color 100 endpoint 1.1.1.1
router2(config-sr-te-policy)# candidate-path preference 1 name mpls explicit segment-list test_mpls
  <cr>
router2(config-sr-te-policy)# candidate-path preference 1 name mpls explicit segment-list test_mpls
router2(config-sr-te-policy)# candidate-path preference 2 name srv6 explicit segment-list test_srv6
% Configuration failed.

Error type: validation
Error description: The Segment List type(2) and Policy type(1) must match!
router2(config-sr-te-policy)# exit
router2(config-sr-te)# policy color 200 endpoint 1:1::1
router2(config-sr-te-policy)# candidate-path preference 1 name srv6 explicit segment-list test_srv6
router2(config-sr-te-policy)# candidate-path preference 2 name mpls explicit segment-list test_mpls
% Configuration failed.

Error type: validation
Error description: The Segment List type(1) and Policy type(2) must match!

config:

segment-routing
 traffic-eng
  segment-list test_srv6
   index 10 ipv6-address 100:1::1
   index 20 ipv6-address 200:1::1
  exit
  segment-list test_mpls
   index 10 mpls label 100
   index 20 mpls label 200
  exit
  policy color 100 endpoint 1.1.1.1
   candidate-path preference 1 name mpls explicit segment-list test_mpls
  exit
  policy color 200 endpoint 1:1::1
   candidate-path preference 1 name srv6 explicit segment-list test_srv6
  exit
 exit
exit
!
end

show:
router2# show sr-te policy detail

Endpoint: 1.1.1.1  Color: 100  Name:   BSID: -  Status: Inactive Type: MPLS
  * Preference: 1  Name: mpls  Type: explicit  Segment-List: test_mpls  Protocol-Origin: Local

Endpoint: 1:1::1  Color: 200  Name:   BSID: -  Status: Active Type: SRV6
  * Preference: 1  Name: srv6  Type: explicit  Segment-List: test_srv6  Protocol-Origin: Local

router2#

Signed-off-by: guozhongfeng.gzf <guozhongfeng.gzf@alibaba-inc.com>
---
 lib/log.c              |   4 +-
 lib/prefix.c           |  18 ++++++
 lib/prefix.h           |   1 +
 lib/srv6.c             |  15 +++++
 lib/srv6.h             |   3 +-
 lib/zclient.c          |  69 +++++++++++++++++++-
 lib/zclient.h          |  10 +++
 pathd/path_cli.c       | 116 ++++++++++++++++++++++++---------
 pathd/path_nb.c        |   8 +++
 pathd/path_nb.h        |   7 ++
 pathd/path_nb_config.c |  66 +++++++++++++++++--
 pathd/path_nb_state.c  |  63 ++++++++++++++++++
 pathd/path_zebra.c     |  39 +++++++++++
 pathd/path_zebra.h     |   5 +-
 pathd/pathd.c          |  68 +++++++++++++------
 pathd/pathd.h          |  19 ++++++
 yang/frr-pathd.yang    | 144 +++++++++++++++++++++--------------------
 zebra/zapi_msg.c       |  12 ++++
 zebra/zebra_srte.h     |   8 +++
 19 files changed, 545 insertions(+), 130 deletions(-)

diff --git a/lib/log.c b/lib/log.c
index bc1ed5c5ccae..6050464feea3 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -464,7 +464,9 @@ static const struct zebra_desc_table command_types[] = {
 	DESC_ENTRY(ZEBRA_TC_FILTER_ADD),
 	DESC_ENTRY(ZEBRA_TC_FILTER_DELETE),
 	DESC_ENTRY(ZEBRA_OPAQUE_NOTIFY),
-	DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY)
+	DESC_ENTRY(ZEBRA_SRV6_SID_NOTIFY),
+	DESC_ENTRY(ZEBRA_SRV6_POLICY_SET),
+	DESC_ENTRY(ZEBRA_SRV6_POLICY_DELETE)
 };
 #undef DESC_ENTRY
 
diff --git a/lib/prefix.c b/lib/prefix.c
index 2485c3e61bdd..eb16d3662d5a 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1124,6 +1124,24 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
 	return str;
 }
 
+int prefix2ipaddr(union prefixconstptr pu, struct ipaddr *ip)
+{
+	const struct prefix *p = pu.p;
+
+	memset(ip, 0, sizeof(struct ipaddr));
+
+	if (p->family == AF_INET) {
+		ip->ipa_type = IPADDR_V4;
+		IPV4_ADDR_COPY(&ip->ipaddr_v4, &p->u.prefix4);
+	} else if (p->family == AF_INET6) {
+		ip->ipa_type = IPADDR_V6;
+		IPV6_ADDR_COPY(&ip->ipaddr_v6, &p->u.prefix6);
+	} else
+		return -1;
+
+	return 0;
+}
+
 void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
 			  char *buf, int buf_size)
 {
diff --git a/lib/prefix.h b/lib/prefix.h
index 2d679d06224f..7baa540899ff 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -422,6 +422,7 @@ extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
 extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
 extern const char *prefix2str(union prefixconstptr upfx, char *buffer,
 			      int size);
+extern int prefix2ipaddr(union prefixconstptr pu, struct ipaddr *ip);
 extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx,
 				   const struct prefix *match_pfx);
 extern int prefix_match(union prefixconstptr unet, union prefixconstptr upfx);
diff --git a/lib/srv6.c b/lib/srv6.c
index e6fc375fbb11..37d8f020066e 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -71,6 +71,21 @@ int snprintf_seg6_segs(char *str,
 	return strlen(str);
 }
 
+int snprintf_seg6_seg_stack(char *str,
+		size_t size, const struct seg6_seg_stack *segs)
+{
+	str[0] = '\0';
+	for (size_t i = 0; i < segs->num_segs; i++) {
+		char addr[INET6_ADDRSTRLEN];
+		bool not_last = (i + 1) < segs->num_segs;
+
+		inet_ntop(AF_INET6, &segs->seg[i], addr, sizeof(addr));
+		strlcat(str, addr, size);
+		strlcat(str, not_last ? "," : "", size);
+	}
+	return strlen(str);
+}
+
 void seg6local_context2json(const struct seg6local_context *ctx,
 			    uint32_t action, json_object *json)
 {
diff --git a/lib/srv6.h b/lib/srv6.h
index 9a041e3d85b2..ee69f41eed1b 100644
--- a/lib/srv6.h
+++ b/lib/srv6.h
@@ -375,7 +375,8 @@ static inline const char *srv6_sid_ctx2str(char *str, size_t size,
 
 int snprintf_seg6_segs(char *str,
 		size_t size, const struct seg6_segs *segs);
-
+int snprintf_seg6_seg_stack(char *str,
+		size_t size, const struct seg6_seg_stack *segs);
 extern struct srv6_locator *srv6_locator_alloc(const char *name);
 extern struct srv6_locator_chunk *srv6_locator_chunk_alloc(void);
 extern void srv6_locator_free(struct srv6_locator *locator);
diff --git a/lib/zclient.c b/lib/zclient.c
index 55bbc18a87eb..46d2208d7ba0 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -3849,8 +3849,14 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
 enum zclient_send_status zebra_send_sr_policy(struct zclient *zclient, int cmd,
 					      struct zapi_sr_policy *zp)
 {
-	if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
-		return ZCLIENT_SEND_FAILURE;
+	if (cmd == ZEBRA_SR_POLICY_SET || cmd == ZEBRA_SR_POLICY_DELETE) {
+		if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
+			return ZCLIENT_SEND_FAILURE;
+	} else if (cmd == ZEBRA_SRV6_POLICY_SET || cmd == ZEBRA_SRV6_POLICY_DELETE) {
+		if (zapi_srv6_policy_encode(zclient->obuf, cmd, zp) < 0)
+			return ZCLIENT_SEND_FAILURE;
+	}
+
 	return zclient_send_message(zclient);
 }
 
@@ -3916,6 +3922,65 @@ int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
 	return -1;
 }
 
+int zapi_srv6_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp)
+{
+	struct zapi_srv6te_tunnel *zt = &zp->segment_list_v6;
+
+	stream_reset(s);
+
+	zclient_create_header(s, cmd, VRF_DEFAULT);
+	stream_putl(s, zp->color);
+	stream_put_ipaddr(s, &zp->endpoint);
+	stream_write(s, &zp->name, SRTE_POLICY_NAME_MAX_LENGTH);
+
+	if (zt->seg_num > SRV6_MAX_SEGS) {
+		flog_err(EC_LIB_ZAPI_ENCODE,
+			 "%s: seg: can't encode %u segs (maximum is %u)",
+			 __func__,  zt->seg_num, SRV6_MAX_SEGS);
+		return -1;
+	}
+
+	stream_putw(s, zt->seg_num);
+
+	for (int i = 0; i < zt->seg_num; i++)
+		stream_put_ipaddr(s, &zt->segs[i]);
+
+	/* Put length at the first point of the stream. */
+	stream_putw_at(s, 0, stream_get_endp(s));
+
+	return 0;
+}
+
+int zapi_srv6_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
+{
+	memset(zp, 0, sizeof(*zp));
+
+	struct zapi_srv6te_tunnel *zt = &zp->segment_list_v6;
+
+	STREAM_GETL(s, zp->color);
+	STREAM_GET_IPADDR(s, &zp->endpoint);
+	STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
+
+	/* segment list of active candidate path */
+	STREAM_GETW(s, zt->seg_num);
+
+	if (zt->seg_num > SRV6_MAX_SEGS) {
+		flog_err(EC_LIB_ZAPI_ENCODE,
+			 "%s: seg: can't decode %u segs (maximum is %u)",
+			 __func__,  zt->seg_num, SRV6_MAX_SEGS);
+		return -1;
+	}
+
+	for (int i = 0; i < zt->seg_num; i++)
+		STREAM_GET_IPADDR(s, &zt->segs[i]);
+
+	return 0;
+
+stream_failure:
+	return -1;
+}
+
+
 int zapi_sr_policy_notify_status_decode(struct stream *s,
 					struct zapi_sr_policy *zp)
 {
diff --git a/lib/zclient.h b/lib/zclient.h
index 8cac6969ee5c..360ee78b467d 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -74,6 +74,7 @@ typedef uint16_t zebra_size_t;
 #define NEXTHOP_REGISTER_FLAG_RESOLVE_VIA_DEFAULT (1 << 1)
 #define NEXTHOP_REGISTER_FLAG_COLOR               (1 << 2)
 
+
 /* Client capabilities */
 enum zserv_client_capabilities {
 	ZEBRA_CLIENT_GR_CAPABILITIES = 1,
@@ -242,6 +243,8 @@ typedef enum {
 	ZEBRA_TC_FILTER_DELETE,
 	ZEBRA_OPAQUE_NOTIFY,
 	ZEBRA_SRV6_SID_NOTIFY,
+	ZEBRA_SRV6_POLICY_SET,
+	ZEBRA_SRV6_POLICY_DELETE,
 } zebra_message_types_t;
 /* Zebra message types. Please update the corresponding
  * command_types array with any changes!
@@ -640,11 +643,16 @@ struct zapi_srte_tunnel {
 	mpls_label_t labels[MPLS_MAX_LABELS];
 };
 
+struct zapi_srv6te_tunnel {
+	uint8_t seg_num;
+	struct ipaddr segs[SRV6_MAX_SEGS];
+};
 struct zapi_sr_policy {
 	uint32_t color;
 	struct ipaddr endpoint;
 	char name[SRTE_POLICY_NAME_MAX_LENGTH];
 	struct zapi_srte_tunnel segment_list;
+	struct zapi_srv6te_tunnel segment_list_v6;
 	int status;
 };
 
@@ -1110,6 +1118,8 @@ extern int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp);
 extern int zapi_sr_policy_notify_status_decode(struct stream *s,
 					       struct zapi_sr_policy *zp);
 
+extern int zapi_srv6_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp);
+extern int zapi_srv6_policy_decode(struct stream *s, struct zapi_sr_policy *zp);
 extern enum zclient_send_status zebra_send_mpls_labels(struct zclient *zclient,
 						       int cmd,
 						       struct zapi_labels *zl);
diff --git a/pathd/path_cli.c b/pathd/path_cli.c
index bf8a9ea02841..dbd54ffdeac1 100644
--- a/pathd/path_cli.c
+++ b/pathd/path_cli.c
@@ -106,7 +106,7 @@ DEFPY(show_srte_policy,
 
 	/* Prepare table. */
 	tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
-	ttable_add_row(tt, "Endpoint|Color|Name|BSID|Status");
+	ttable_add_row(tt, "Endpoint|Color|Name|BSID|Status|Type");
 	tt->style.cell.rpad = 2;
 	tt->style.corner = '+';
 	ttable_restyle(tt);
@@ -121,11 +121,12 @@ DEFPY(show_srte_policy,
 			snprintf(binding_sid, sizeof(binding_sid), "%u",
 				 policy->binding_sid);
 
-		ttable_add_row(tt, "%s|%u|%s|%s|%s", endpoint, policy->color,
-			       policy->name, binding_sid,
-			       policy->status == SRTE_POLICY_STATUS_UP
-				       ? "Active"
-				       : "Inactive");
+		ttable_add_row(tt, "%s|%u|%s|%s|%s|%s", endpoint, policy->color,
+				policy->name, binding_sid,
+				policy->status == SRTE_POLICY_STATUS_UP ? "Active" : "Inactive",
+				policy->type == SRTE_POLICY_TYPE_MPLS
+					? "MPLS"
+					: (policy->type == SRTE_POLICY_TYPE_SRV6 ? "SRV6" : "Undefined"));
 	}
 
 	/* Dump the generated table. */
@@ -172,37 +173,60 @@ DEFPY(show_srte_policy_detail,
 			snprintf(binding_sid, sizeof(binding_sid), "%u",
 				 policy->binding_sid);
 		vty_out(vty,
-			"Endpoint: %s  Color: %u  Name: %s  BSID: %s  Status: %s\n",
+			"Endpoint: %s  Color: %u  Name: %s  BSID: %s  Status: %s Type: %s\n",
 			endpoint, policy->color, policy->name, binding_sid,
-			policy->status == SRTE_POLICY_STATUS_UP ? "Active"
-								: "Inactive");
+			policy->status == SRTE_POLICY_STATUS_UP ? "Active" : "Inactive",
+			policy->type == SRTE_POLICY_TYPE_MPLS
+				? "MPLS"
+				: (policy->type == SRTE_POLICY_TYPE_SRV6 ? "SRV6" : "Undefined"));
 
 		RB_FOREACH (candidate, srte_candidate_head,
 			    &policy->candidate_paths) {
 			struct srte_segment_list *segment_list;
-
-			segment_list = candidate->lsp->segment_list;
-			if (segment_list == NULL)
-				segment_list_info = undefined_info;
-			else if (segment_list->protocol_origin
-				 == SRTE_ORIGIN_PCEP)
-				segment_list_info = created_by_pce_info;
-			else
-				segment_list_info =
-					candidate->lsp->segment_list->name;
-
-			vty_out(vty,
-				"  %s Preference: %d  Name: %s  Type: %s  Segment-List: %s  Protocol-Origin: %s\n",
-				CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
-					? "*"
-					: " ",
-				candidate->preference, candidate->name,
-				candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
-					? "explicit"
-					: "dynamic",
-				segment_list_info,
-				srte_origin2str(
-					candidate->lsp->protocol_origin));
+			if (policy->type == SRTE_POLICY_TYPE_MPLS) {
+				segment_list = candidate->lsp->segment_list;
+				if (segment_list == NULL)
+					segment_list_info = undefined_info;
+				else if (segment_list->protocol_origin
+					== SRTE_ORIGIN_PCEP)
+					segment_list_info = created_by_pce_info;
+				else
+					segment_list_info =
+						candidate->lsp->segment_list->name;
+
+				vty_out(vty,
+					"  %s Preference: %d  Name: %s  Type: %s  Segment-List: %s  Protocol-Origin: %s\n",
+					CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
+						? "*"
+						: " ",
+					candidate->preference, candidate->name,
+					candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
+						? "explicit"
+						: "dynamic",
+					segment_list_info,
+					srte_origin2str(
+						candidate->lsp->protocol_origin));
+			} else if (policy->type == SRTE_POLICY_TYPE_SRV6) {
+				segment_list = candidate->segment_list;
+				if (segment_list == NULL)
+					segment_list_info = undefined_info;
+				else
+					segment_list_info =
+						candidate->segment_list->name;
+
+				vty_out(vty,
+					"  %s Preference: %d  Name: %s  Type: %s  Segment-List: %s  Protocol-Origin: %s\n",
+					CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
+						? "*"
+						: " ",
+					candidate->preference, candidate->name,
+					candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
+						? "explicit"
+						: "dynamic",
+					segment_list_info,
+					srte_origin2str(
+						candidate->protocol_origin));
+			}
 		}
 
 		vty_out(vty, "\n");
@@ -308,6 +332,7 @@ static int segment_list_has_src_dst(
 
 	struct ipaddr ip_src = {};
 	struct ipaddr ip_dst = {};
+
 	if (adj_src_ipv4_str != NULL) {
 		ip_src.ipa_type = IPADDR_V4;
 		ip_src.ip._v4_addr = adj_src_ipv4;
@@ -527,6 +552,24 @@ DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
 	return nb_cli_apply_changes(vty, NULL);
 }
 
+DEFPY_YANG(srv6te_segment_list_segment, srv6te_segment_list_segment_cmd,
+      "index (0-4294967295)$index ipv6-address  X:X::X:X$ipv6_addr",
+      "Index\n"
+      "Index Value\n"
+      IPV6_STR
+      "IPv6 address\n")
+{
+	char xpath[XPATH_MAXLEN];
+
+	snprintf(xpath, sizeof(xpath), "./segment[index='%s']", index_str);
+	nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+	snprintf(xpath, sizeof(xpath),
+			"./segment[index='%s']/srv6-sid-value", index_str);
+	nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, ipv6_addr_str);
+	return nb_cli_apply_changes(vty, NULL);
+}
+
 DEFPY(srte_segment_list_no_segment,
       srte_segment_list_no_segment_cmd,
       "no index (0-4294967295)$index",
@@ -547,10 +590,17 @@ void cli_show_srte_segment_list_segment(struct vty *vty,
 					bool show_defaults)
 {
 	vty_out(vty, "   index %s", yang_dnode_get_string(dnode, "index"));
+
+	if (yang_dnode_exists(dnode, "srv6-sid-value")) {
+		vty_out(vty, " ipv6-address %s",
+			yang_dnode_get_string(dnode, "srv6-sid-value"));
+	}
+
 	if (yang_dnode_exists(dnode, "sid-value")) {
 		vty_out(vty, " mpls label %s",
 			yang_dnode_get_string(dnode, "sid-value"));
 	}
+
 	if (yang_dnode_exists(dnode, "nai")) {
 		struct ipaddr addr;
 		struct ipaddr addr_rmt;
@@ -1331,6 +1381,8 @@ void path_cli_init(void)
 	install_element(SR_TRAFFIC_ENG_NODE, &srte_no_segment_list_cmd);
 	install_element(SR_SEGMENT_LIST_NODE,
 			&srte_segment_list_segment_cmd);
+	install_element(SR_SEGMENT_LIST_NODE,
+			&srv6te_segment_list_segment_cmd);
 	install_element(SR_SEGMENT_LIST_NODE,
 			&srte_segment_list_no_segment_cmd);
 	install_element(SR_TRAFFIC_ENG_NODE, &srte_policy_cmd);
diff --git a/pathd/path_nb.c b/pathd/path_nb.c
index e1c0cc3efa6c..523d3152434a 100644
--- a/pathd/path_nb.c
+++ b/pathd/path_nb.c
@@ -82,6 +82,14 @@ const struct frr_yang_module_info frr_pathd_info = {
 			},
 			.priority = NB_DFLT_PRIORITY - 1
 		},
+		{
+			.xpath = "/frr-pathd:pathd/srte/segment-list/segment/srv6-sid-value",
+			.cbs = {
+				.modify = pathd_srte_segment_list_segment_v6_sid_value_modify,
+				.destroy = pathd_srte_segment_list_segment_v6_sid_value_destroy,
+			},
+			.priority = NB_DFLT_PRIORITY - 1
+		},
 		{
 			.xpath = "/frr-pathd:pathd/srte/segment-list/segment/nai",
 			.cbs = {
diff --git a/pathd/path_nb.h b/pathd/path_nb.h
index 21876d788303..4d1895cc3a3e 100644
--- a/pathd/path_nb.h
+++ b/pathd/path_nb.h
@@ -20,6 +20,7 @@ const void *
 pathd_srte_segment_list_lookup_entry(struct nb_cb_lookup_entry_args *args);
 
 int pathd_srte_segment_list_segment_create(struct nb_cb_create_args *args);
+int pathd_srte_segment_list_segment_check_validate(struct nb_cb_create_args *args);
 int pathd_srte_segment_list_segment_destroy(struct nb_cb_destroy_args *args);
 int pathd_srte_segment_list_protocol_origin_modify(
 	struct nb_cb_modify_args *args);
@@ -32,6 +33,10 @@ void pathd_srte_segment_list_segment_nai_apply_finish(
 	struct nb_cb_apply_finish_args *args);
 int pathd_srte_segment_list_segment_sid_value_destroy(
 	struct nb_cb_destroy_args *args);
+int pathd_srte_segment_list_segment_v6_sid_value_modify(
+	struct nb_cb_modify_args *args);
+int pathd_srte_segment_list_segment_v6_sid_value_destroy(
+	struct nb_cb_destroy_args *args);
 int pathd_srte_policy_create(struct nb_cb_create_args *args);
 int pathd_srte_policy_destroy(struct nb_cb_destroy_args *args);
 const void *pathd_srte_policy_get_next(struct nb_cb_get_next_args *args);
@@ -53,6 +58,8 @@ pathd_srte_policy_candidate_path_get_next(struct nb_cb_get_next_args *args);
 int pathd_srte_policy_candidate_path_get_keys(struct nb_cb_get_keys_args *args);
 const void *pathd_srte_policy_candidate_path_lookup_entry(
 	struct nb_cb_lookup_entry_args *args);
+int pathd_srte_policy_candidate_path_check_validate(
+	struct nb_cb_create_args *args);
 void pathd_srte_policy_candidate_path_bandwidth_apply_finish(
 	struct nb_cb_apply_finish_args *args);
 int pathd_srte_policy_candidate_path_bandwidth_destroy(
diff --git a/pathd/path_nb_config.c b/pathd/path_nb_config.c
index 48531ba43339..912c0587ff8d 100644
--- a/pathd/path_nb_config.c
+++ b/pathd/path_nb_config.c
@@ -96,9 +96,16 @@ int pathd_srte_segment_list_originator_modify(struct nb_cb_modify_args *args)
  */
 int pathd_srte_segment_list_segment_create(struct nb_cb_create_args *args)
 {
-	struct srte_segment_list *segment_list;
 	struct srte_segment_entry *segment;
+	struct srte_segment_list *segment_list;
 	uint32_t index;
+	enum nb_error nb_code = NB_OK;
+
+	if (args->event == NB_EV_VALIDATE) {
+		nb_code = pathd_srte_segment_list_segment_check_validate(args);
+		if (nb_code != NB_OK)
+			return nb_code;
+	}
 
 	if (args->event != NB_EV_APPLY)
 		return NB_OK;
@@ -142,6 +149,7 @@ int pathd_srte_segment_list_segment_sid_value_modify(
 	segment = nb_running_get_entry(args->dnode, NULL, true);
 	sid_value = yang_dnode_get_uint32(args->dnode, NULL);
 	segment->sid_value = sid_value;
+	segment->segment_list->type = SRTE_SEGMENT_LIST_TYPE_MPLS;
 	SET_FLAG(segment->segment_list->flags, F_SEGMENT_LIST_MODIFIED);
 
 	return NB_OK;
@@ -162,6 +170,41 @@ int pathd_srte_segment_list_segment_sid_value_destroy(
 	return NB_OK;
 }
 
+/*
+ * XPath: /frr-pathd:pathd/srte/segment-list/segment/srv6-sid-value
+ */
+int pathd_srte_segment_list_segment_v6_sid_value_modify(
+	struct nb_cb_modify_args *args)
+{
+	struct ipaddr sid_value;
+	struct srte_segment_entry *segment;
+
+	if (args->event != NB_EV_APPLY)
+		return NB_OK;
+
+	segment = nb_running_get_entry(args->dnode, NULL, true);
+	yang_dnode_get_ip(&sid_value, args->dnode, NULL);
+	segment->srv6_sid_value = sid_value;
+	segment->segment_list->type = SRTE_SEGMENT_LIST_TYPE_SRV6;
+	SET_FLAG(segment->segment_list->flags, F_SEGMENT_LIST_MODIFIED);
+
+	return NB_OK;
+}
+
+int pathd_srte_segment_list_segment_v6_sid_value_destroy(
+	struct nb_cb_destroy_args *args)
+{
+	struct srte_segment_entry *segment;
+
+	if (args->event != NB_EV_APPLY)
+		return NB_OK;
+
+	segment = nb_running_get_entry(args->dnode, NULL, true);
+	memset(&segment->srv6_sid_value, 0, sizeof(struct ipaddr));
+	SET_FLAG(segment->segment_list->flags, F_SEGMENT_LIST_MODIFIED);
+
+	return NB_OK;
+}
 
 int pathd_srte_segment_list_segment_nai_destroy(struct nb_cb_destroy_args *args)
 {
@@ -235,11 +278,14 @@ void pathd_srte_segment_list_segment_nai_apply_finish(
 
 	zlog_debug(" Segment list name (%d) index (%s) ", segment->index,
 		   segment->segment_list->name);
+
 	if (srte_segment_entry_set_nai(segment, type, &local_addr, local_iface,
-				       &remote_addr, remote_iface, algo,
-				       local_prefix_len))
+					&remote_addr, remote_iface, algo,
+					local_prefix_len)) {
 		SET_FLAG(segment->segment_list->flags,
 			 F_SEGMENT_LIST_SID_CONFLICT);
+		segment->segment_list->type = SRTE_SEGMENT_LIST_TYPE_MPLS;
+	}
 }
 
 /*
@@ -372,7 +418,13 @@ int pathd_srte_policy_candidate_path_create(struct nb_cb_create_args *args)
 	struct srte_policy *policy;
 	struct srte_candidate *candidate;
 	uint32_t preference;
+	enum nb_error nb_code = NB_OK;
 
+	if (args->event == NB_EV_VALIDATE) {
+		nb_code = pathd_srte_policy_candidate_path_check_validate(args);
+		if (nb_code != NB_OK)
+			return nb_code;
+	}
 	if (args->event != NB_EV_APPLY)
 		return NB_OK;
 
@@ -703,7 +755,13 @@ int pathd_srte_policy_candidate_path_segment_list_name_modify(
 	segment_list_name = yang_dnode_get_string(args->dnode, NULL);
 
 	candidate->segment_list = srte_segment_list_find(segment_list_name);
-	candidate->lsp->segment_list = candidate->segment_list;
+
+	if (candidate->segment_list->type == SRTE_SEGMENT_LIST_TYPE_MPLS) {
+		candidate->lsp->segment_list = candidate->segment_list;
+		candidate->policy->type = SRTE_POLICY_TYPE_MPLS;
+	} else if (candidate->segment_list->type == SRTE_SEGMENT_LIST_TYPE_SRV6)
+		candidate->policy->type = SRTE_POLICY_TYPE_SRV6;
+
 	assert(candidate->segment_list);
 	SET_FLAG(candidate->flags, F_CANDIDATE_MODIFIED);
 
diff --git a/pathd/path_nb_state.c b/pathd/path_nb_state.c
index 35b9e37c7370..d5a4d1460acf 100644
--- a/pathd/path_nb_state.c
+++ b/pathd/path_nb_state.c
@@ -4,6 +4,7 @@
  */
 
 #include <zebra.h>
+#include <lib_errors.h>
 
 #include "log.h"
 #include "prefix.h"
@@ -149,6 +150,68 @@ const void *pathd_srte_policy_candidate_path_lookup_entry(
 	return srte_candidate_find(policy, preference);
 }
 
+int pathd_srte_segment_list_segment_check_validate(struct nb_cb_create_args *args)
+{
+	struct srte_segment_list *segment_list;
+
+	segment_list = nb_running_get_entry(args->dnode, NULL, false);
+	if (segment_list == NULL)
+		return NB_OK;
+
+	if (yang_dnode_exists(args->dnode, "sid-value") || yang_dnode_exists(args->dnode, "nai")) {
+		if (segment_list->type == SRTE_SEGMENT_LIST_TYPE_SRV6) {
+			snprintf(args->errmsg, args->errmsg_len,
+				"The Segment List(%s) Type must be SRv6!", segment_list->name);
+			flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE,
+				"The Segment List(%s) Type must be SRv6!", segment_list->name);
+			return NB_ERR_VALIDATION;
+		} else
+			return NB_OK;
+	}
+
+	if (yang_dnode_exists(args->dnode, "srv6-sid-value")) {
+		if (segment_list->type == SRTE_SEGMENT_LIST_TYPE_MPLS) {
+			snprintf(args->errmsg, args->errmsg_len,
+				"The Segment List(%s) Type must be MPLS!", segment_list->name);
+			flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE,
+				"The Segment List(%s) Type must be MPLS!",  segment_list->name);
+			return NB_ERR_VALIDATION;
+		} else
+			return NB_OK;
+	}
+	return NB_OK;
+}
+
+int pathd_srte_policy_candidate_path_check_validate(
+	struct nb_cb_create_args *args)
+{
+	struct srte_policy *policy;
+	const char *segment_list_name;
+	struct srte_segment_list *segment_list;
+
+	policy = nb_running_get_entry(args->dnode, NULL, false);
+	segment_list_name = yang_dnode_get_string(args->dnode, "segment-list-name");
+	segment_list = srte_segment_list_find(segment_list_name);
+
+	if (segment_list == NULL)
+		return NB_OK;
+
+	if ((segment_list->type == SRTE_SEGMENT_LIST_TYPE_SRV6
+		&& policy->type == SRTE_POLICY_TYPE_MPLS)
+		|| (segment_list->type == SRTE_SEGMENT_LIST_TYPE_MPLS
+		&& policy->type == SRTE_POLICY_TYPE_SRV6)) {
+		snprintf(args->errmsg, args->errmsg_len,
+			"The Segment List type(%d) and Policy type(%d) must match!",
+			segment_list->type, policy->type);
+		flog_warn(EC_LIB_NB_CB_CONFIG_VALIDATE,
+			"The Segment List type(%d) and Policy type(%d) must match!",
+			segment_list->type, policy->type);
+		return NB_ERR_VALIDATION;
+	}
+
+	return NB_OK;
+}
+
 /*
  * XPath: /frr-pathd:pathd/srte/policy/candidate_path/is-best-candidate-path
  */
diff --git a/pathd/path_zebra.c b/pathd/path_zebra.c
index ba03315c82f7..6beb791e3984 100644
--- a/pathd/path_zebra.c
+++ b/pathd/path_zebra.c
@@ -212,6 +212,45 @@ void path_zebra_delete_sr_policy(struct srte_policy *policy)
 	(void)zebra_send_sr_policy(zclient, ZEBRA_SR_POLICY_DELETE, &zp);
 }
 
+/**
+ * Adds a segment routing policy to Zebra.
+ *
+ * @param policy The policy to add
+ * @param segment_list The segment list for the policy
+ */
+void path_zebra_add_srv6_policy(struct srte_policy *policy,
+			      struct srte_segment_list *segment_list)
+{
+	struct zapi_sr_policy zp = {};
+	struct srte_segment_entry *segment;
+
+	zp.color = policy->color;
+	zp.endpoint = policy->endpoint;
+	strlcpy(zp.name, policy->name, sizeof(zp.name));
+	zp.segment_list_v6.seg_num = 0;
+	RB_FOREACH (segment, srte_segment_entry_head, &segment_list->segments) {
+		memcpy(&zp.segment_list_v6.segs[zp.segment_list_v6.seg_num],
+			&segment->srv6_sid_value, sizeof(struct ipaddr));
+		zp.segment_list_v6.seg_num++;
+	}
+	policy->status = SRTE_POLICY_STATUS_UP;
+
+	(void)zebra_send_sr_policy(zclient, ZEBRA_SRV6_POLICY_SET, &zp);
+}
+
+void path_zebra_delete_srv6_policy(struct srte_policy *policy)
+{
+	struct zapi_sr_policy zp = {};
+
+	zp.color = policy->color;
+	zp.endpoint = policy->endpoint;
+	strlcpy(zp.name, policy->name, sizeof(zp.name));
+	zp.segment_list_v6.seg_num = 0;
+	policy->status = SRTE_POLICY_STATUS_DOWN;
+
+	(void)zebra_send_sr_policy(zclient, ZEBRA_SRV6_POLICY_DELETE, &zp);
+}
+
 /**
  * Allocates a label from Zebra's label manager.
  *
diff --git a/pathd/path_zebra.h b/pathd/path_zebra.h
index 74a62e38b328..11d179d2f4d8 100644
--- a/pathd/path_zebra.h
+++ b/pathd/path_zebra.h
@@ -12,8 +12,11 @@
 bool get_ipv4_router_id(struct in_addr *router_id);
 bool get_ipv6_router_id(struct in6_addr *router_id);
 void path_zebra_add_sr_policy(struct srte_policy *policy,
-			      struct srte_segment_list *segment_list);
+					struct srte_segment_list *segment_list);
 void path_zebra_delete_sr_policy(struct srte_policy *policy);
+void path_zebra_add_srv6_policy(struct srte_policy *policy,
+					struct srte_segment_list *segment_list);
+void path_zebra_delete_srv6_policy(struct srte_policy *policy);
 int path_zebra_request_label(mpls_label_t label);
 void path_zebra_release_label(mpls_label_t label);
 void path_zebra_init(struct event_loop *master);
diff --git a/pathd/pathd.c b/pathd/pathd.c
index 431fe4d1e31e..469b91143d68 100644
--- a/pathd/pathd.c
+++ b/pathd/pathd.c
@@ -121,6 +121,7 @@ struct srte_segment_list *srte_segment_list_add(const char *name)
 
 	segment_list = XCALLOC(MTYPE_PATH_SEGMENT_LIST, sizeof(*segment_list));
 	strlcpy(segment_list->name, name, sizeof(segment_list->name));
+	segment_list->type = SRTE_SEGMENT_LIST_TYPE_UNDEFINED;
 	RB_INIT(srte_segment_entry_head, &segment_list->segments);
 	RB_INSERT(srte_segment_list_head, &srte_segment_lists, segment_list);
 
@@ -329,6 +330,7 @@ struct srte_policy *srte_policy_add(uint32_t color, struct ipaddr *endpoint,
 	policy->endpoint = *endpoint;
 	policy->binding_sid = MPLS_LABEL_NONE;
 	policy->protocol_origin = origin;
+	policy->type = SRTE_POLICY_TYPE_UNDEFINED;
 	if (originator != NULL)
 		strlcpy(policy->originator, originator,
 			sizeof(policy->originator));
@@ -351,9 +353,14 @@ void srte_policy_del(struct srte_policy *policy)
 {
 	struct srte_candidate *candidate;
 
-	path_zebra_delete_sr_policy(policy);
+	if (policy->type == SRTE_POLICY_TYPE_MPLS) {
+		path_zebra_delete_sr_policy(policy);
 
-	path_zebra_release_label(policy->binding_sid);
+		path_zebra_release_label(policy->binding_sid);
+	}
+
+	if (policy->type == SRTE_POLICY_TYPE_SRV6)
+		path_zebra_delete_srv6_policy(policy);
 
 	while (!RB_EMPTY(srte_candidate_head, &policy->candidate_paths)) {
 		candidate =
@@ -518,14 +525,23 @@ srte_policy_best_candidate(const struct srte_policy *policy)
 {
 	struct srte_candidate *candidate;
 
-	RB_FOREACH_REVERSE (candidate, srte_candidate_head,
-			    &policy->candidate_paths) {
-		/* search for highest preference with existing segment list */
-		if (!CHECK_FLAG(candidate->flags, F_CANDIDATE_DELETED)
-		    && candidate->lsp->segment_list
-		    && (!CHECK_FLAG(candidate->lsp->segment_list->flags,
-				    F_SEGMENT_LIST_SID_CONFLICT)))
-			return candidate;
+	if (policy->type == SRTE_POLICY_TYPE_MPLS) {
+		RB_FOREACH_REVERSE (candidate, srte_candidate_head,
+				&policy->candidate_paths) {
+			/* search for highest preference with existing segment list */
+			if (!CHECK_FLAG(candidate->flags, F_CANDIDATE_DELETED)
+				&& candidate->lsp->segment_list
+				&& (!CHECK_FLAG(candidate->lsp->segment_list->flags,
+						F_SEGMENT_LIST_SID_CONFLICT)))
+				return candidate;
+		}
+	} else if (policy->type == SRTE_POLICY_TYPE_SRV6) {
+		RB_FOREACH_REVERSE (candidate, srte_candidate_head,
+				&policy->candidate_paths) {
+			if (!CHECK_FLAG(candidate->flags, F_CANDIDATE_DELETED)
+				&& candidate->segment_list)
+				return candidate;
+		}
 	}
 
 	return NULL;
@@ -598,6 +614,9 @@ void srte_policy_apply_changes(struct srte_policy *policy)
 	struct srte_candidate *new_best_candidate;
 	char endpoint[ENDPOINT_STR_LENGTH];
 
+	if (policy->type != SRTE_POLICY_TYPE_MPLS && policy->type != SRTE_POLICY_TYPE_SRV6)
+		return;
+
 	ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
 
 	/* Get old and new best candidate path. */
@@ -621,17 +640,24 @@ void srte_policy_apply_changes(struct srte_policy *policy)
 			 * Rely on replace semantics if there's a new best
 			 * candidate.
 			 */
-			if (!new_best_candidate)
-				path_zebra_delete_sr_policy(policy);
+			if (!new_best_candidate) {
+				if (policy->type == SRTE_POLICY_TYPE_MPLS)
+					path_zebra_delete_sr_policy(policy);
+				else
+					path_zebra_delete_srv6_policy(policy);
+			}
 		}
 		if (new_best_candidate) {
 			policy->best_candidate = new_best_candidate;
 			SET_FLAG(new_best_candidate->flags, F_CANDIDATE_BEST);
 			SET_FLAG(new_best_candidate->flags,
 				 F_CANDIDATE_MODIFIED);
-
-			path_zebra_add_sr_policy(
-				policy, new_best_candidate->lsp->segment_list);
+			if (policy->type == SRTE_POLICY_TYPE_MPLS)
+				path_zebra_add_sr_policy(
+					policy, new_best_candidate->lsp->segment_list);
+			else
+				path_zebra_add_srv6_policy(
+					policy, new_best_candidate->segment_list);
 		}
 	} else if (new_best_candidate) {
 		/* The best candidate path did not change, but some of its
@@ -652,8 +678,12 @@ void srte_policy_apply_changes(struct srte_policy *policy)
 				endpoint, policy->color,
 				new_best_candidate->name);
 
-			path_zebra_add_sr_policy(
-				policy, new_best_candidate->lsp->segment_list);
+			if (policy->type == SRTE_POLICY_TYPE_MPLS)
+				path_zebra_add_sr_policy(
+					policy, new_best_candidate->lsp->segment_list);
+			else
+				path_zebra_add_srv6_policy(
+					policy, new_best_candidate->segment_list);
 		}
 	}
 
@@ -734,8 +764,8 @@ void srte_candidate_del(struct srte_candidate *candidate)
 
 	RB_REMOVE(srte_candidate_head, &srte_policy->candidate_paths,
 		  candidate);
-
-	XFREE(MTYPE_PATH_SR_CANDIDATE, candidate->lsp);
+	if (candidate->lsp)
+		XFREE(MTYPE_PATH_SR_CANDIDATE, candidate->lsp);
 	XFREE(MTYPE_PATH_SR_CANDIDATE, candidate);
 }
 
diff --git a/pathd/pathd.h b/pathd/pathd.h
index 75e7eff920e7..33e8664d929d 100644
--- a/pathd/pathd.h
+++ b/pathd/pathd.h
@@ -153,6 +153,17 @@ enum affinity_filter_type {
 };
 #define MAX_AFFINITY_FILTER_TYPE 3
 
+enum srte_segment_list_type {
+	SRTE_SEGMENT_LIST_TYPE_UNDEFINED = 0,
+	SRTE_SEGMENT_LIST_TYPE_MPLS = 1,
+	SRTE_SEGMENT_LIST_TYPE_SRV6 = 2,
+};
+
+enum srte_policy_type {
+	SRTE_POLICY_TYPE_UNDEFINED = 0,
+	SRTE_POLICY_TYPE_MPLS = 1,
+	SRTE_POLICY_TYPE_SRV6 = 2,
+};
 struct srte_segment_list;
 
 struct srte_segment_entry {
@@ -167,6 +178,9 @@ struct srte_segment_entry {
 	/* Label Value. */
 	mpls_label_t sid_value;
 
+	/*Srv6 Sid*/
+	struct ipaddr srv6_sid_value;
+
 	/* NAI Type */
 	enum srte_segment_nai_type nai_type;
 	/* NAI local address when nai type is not NONE */
@@ -201,6 +215,8 @@ struct srte_segment_list {
 	/* Nexthops. */
 	struct srte_segment_entry_head segments;
 
+	enum srte_segment_list_type type;
+
 	/* Status flags. */
 	uint16_t flags;
 #define F_SEGMENT_LIST_NEW 0x0002
@@ -341,6 +357,9 @@ struct srte_policy {
 	/* Operational Status of the policy */
 	enum srte_policy_status status;
 
+	/* The Type (mpls or srv6) */
+	enum srte_policy_type type;
+
 	/* Best candidate path. */
 	struct srte_candidate *best_candidate;
 
diff --git a/yang/frr-pathd.yang b/yang/frr-pathd.yang
index 5beda769c1a3..82a14d3e7826 100644
--- a/yang/frr-pathd.yang
+++ b/yang/frr-pathd.yang
@@ -84,84 +84,88 @@ module frr-pathd {
           leaf index {
             type uint32;
             description "Segment index";
-	  }
-        leaf sid-value {
-          type rt-types:mpls-label;
-          description "MPLS label value";
-        }
-        container nai {
-          presence "The segment has a Node or Adjacency Identifier";
-          leaf type {
-            description "NAI type";
-            mandatory true;
-            type enumeration {
-              enum ipv4_node {
-                value 1;
-                description "IPv4 node identifier";
-              }
-              enum ipv6_node {
-                value 2;
-                description "IPv6 node identifier";
-              }
-              enum ipv4_adjacency {
-                value 3;
-                description "IPv4 adjacency";
-              }
-              enum ipv6_adjacency {
-                value 4;
-                description "IPv6 adjacency";
-              }
-              enum ipv4_unnumbered_adjacency {
-                value 5;
-                description "IPv4 unnumbered adjacency";
-              }
-              enum ipv4_local_iface {
-                value 7;
-                description "IPv4 prefix with local interface id";
-              }
-              enum ipv6_local_iface {
-                value 8;
-                description "IPv6 prefix with local interface id";
-              }
-              enum ipv4_algo {
-                value 9;
-                description "IPv4 prefix with optional algorithm";
-              }
-              enum ipv6_algo {
-                value 10;
-                description "IPv6 prefix with optional algorithm";
-              }
-            }
-          }
-          leaf local-address {
-            type inet:ip-address;
-            mandatory true;
-          }
-          leaf local-prefix-len {
-            type uint8;
-            mandatory true;
-            when "../type = 'ipv4_local_iface' or ../type = 'ipv6_local_iface' or ../type = 'ipv4_algo' or ../type = 'ipv6_algo'";
           }
-          leaf local-interface {
-            type uint32;
-            mandatory true;
-            when "../type = 'ipv4_local_iface' or ../type = 'ipv6_local_iface' or ../type = 'ipv4_unnumbered_adjacency'";
+          leaf sid-value {
+            type rt-types:mpls-label;
+            description "MPLS label value";
           }
-          leaf remote-address {
+          leaf srv6-sid-value {
             type inet:ip-address;
+            description "SRv6 sid value";
+          }
+          container nai {
+            presence "The segment has a Node or Adjacency Identifier";
+            leaf type {
+              description "NAI type";
+              mandatory true;
+              type enumeration {
+                enum ipv4_node {
+                  value 1;
+                  description "IPv4 node identifier";
+                }
+                enum ipv6_node {
+                  value 2;
+                  description "IPv6 node identifier";
+                }
+                enum ipv4_adjacency {
+                  value 3;
+                  description "IPv4 adjacency";
+                }
+                enum ipv6_adjacency {
+                  value 4;
+                  description "IPv6 adjacency";
+                }
+                enum ipv4_unnumbered_adjacency {
+                  value 5;
+                  description "IPv4 unnumbered adjacency";
+                }
+                enum ipv4_local_iface {
+                  value 7;
+                  description "IPv4 prefix with local interface id";
+                }
+                enum ipv6_local_iface {
+                  value 8;
+                  description "IPv6 prefix with local interface id";
+                }
+                enum ipv4_algo {
+                  value 9;
+                  description "IPv4 prefix with optional algorithm";
+                }
+                enum ipv6_algo {
+                  value 10;
+                  description "IPv6 prefix with optional algorithm";
+                }
+              }
+            }
+            leaf local-address {
+              type inet:ip-address;
+              mandatory true;
+            }
+            leaf local-prefix-len {
+              type uint8;
               mandatory true;
-              when "../type = 'ipv4_adjacency' or ../type = 'ipv6_adjacency' or ../type = 'ipv4_unnumbered_adjacency'";
+              when "../type = 'ipv4_local_iface' or ../type = 'ipv6_local_iface' or ../type = 'ipv4_algo' or ../type = 'ipv6_algo'";
             }
-            leaf remote-interface {
+            leaf local-interface {
               type uint32;
               mandatory true;
-              when "../type = 'ipv4_unnumbered_adjacency'";
+              when "../type = 'ipv4_local_iface' or ../type = 'ipv6_local_iface' or ../type = 'ipv4_unnumbered_adjacency'";
+            }
+            leaf remote-address {
+              type inet:ip-address;
+                mandatory true;
+                when "../type = 'ipv4_adjacency' or ../type = 'ipv6_adjacency' or ../type = 'ipv4_unnumbered_adjacency'";
+              }
+              leaf remote-interface {
+                type uint32;
+                mandatory true;
+                when "../type = 'ipv4_unnumbered_adjacency'";
+              }
+            leaf algorithm {
+              type uint8;
+              mandatory true;
+              when "../type = 'ipv4_algo' or ../type = 'ipv6_algo'";
             }
-          leaf algorithm {
-            type uint8;
-            mandatory true;
-            when "../type = 'ipv4_algo' or ../type = 'ipv6_algo'";
-          }
           }
         }
       }
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 198715a657ce..0f0fd74f51c2 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2741,6 +2741,16 @@ static void zread_sr_policy_delete(ZAPI_HANDLER_ARGS)
 	zebra_sr_policy_del(policy);
 }
 
+static void zread_srv6_policy_set(ZAPI_HANDLER_ARGS)
+{
+
+}
+
+static void zread_srv6_policy_delete(ZAPI_HANDLER_ARGS)
+{
+
+}
+
 int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint,
 				  char *name, int status)
 {
@@ -4145,6 +4155,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
 	[ZEBRA_TC_CLASS_DELETE] = zread_tc_class,
 	[ZEBRA_TC_FILTER_ADD] = zread_tc_filter,
 	[ZEBRA_TC_FILTER_DELETE] = zread_tc_filter,
+	[ZEBRA_SRV6_POLICY_SET] = zread_srv6_policy_set,
+	[ZEBRA_SRV6_POLICY_DELETE] = zread_srv6_policy_delete,
 };
 
 /*
diff --git a/zebra/zebra_srte.h b/zebra/zebra_srte.h
index 1cdee454048a..66b6a30d093a 100644
--- a/zebra/zebra_srte.h
+++ b/zebra/zebra_srte.h
@@ -21,13 +21,21 @@ enum zebra_sr_policy_update_label_mode {
 	ZEBRA_SR_POLICY_LABEL_REMOVED = 3,
 };
 
+enum zebra_sr_policy_type {
+	ZEBRA_SR_POLICY_TYPE_UNDEFINED = 0,
+	ZEBRA_SR_POLICY_TYPE_MPLS = 1,
+	ZEBRA_SR_POLICY_TYPE_SRV6 = 2,
+};
+
 struct zebra_sr_policy {
 	RB_ENTRY(zebra_sr_policy) entry;
 	uint32_t color;
 	struct ipaddr endpoint;
 	char name[SRTE_POLICY_NAME_MAX_LENGTH];
 	enum zebra_sr_policy_status status;
+	enum zebra_sr_policy_type type;
 	struct zapi_srte_tunnel segment_list;
+	struct zapi_srv6te_tunnel segment_list_v6;
 	struct zebra_lsp *lsp;
 	struct zebra_vrf *zvrf;
 	int sock;