--- a/net/dccp/ccid.h
+++ b/net/dccp/ccid.h
@@ -40,6 +40,7 @@ struct tcp_info;
  *  @ccid_hc_tx_packet_recv: implements feedback processing for the HC-sender
  *  @ccid_hc_tx_send_packet: implements the sending part of the HC-sender
  *  @ccid_hc_tx_packet_sent: does accounting for packets in flight by HC-sender
+ *  @ccid_hc_tx_probe: CCID-dependent hook for dccp_probe
  *  @ccid_hc_{r,t}x_get_info: INET_DIAG information for HC-receiver/sender
  *  @ccid_hc_{r,t}x_getsockopt: socket options specific to HC-receiver/sender
  */
@@ -70,6 +71,8 @@ struct ccid_operations {
 						  struct sk_buff *skb);
 	void		(*ccid_hc_tx_packet_sent)(struct sock *sk,
 						  unsigned int len);
+	size_t		(*ccid_hc_tx_probe)(struct sock *sk,
+					    char *buf, const size_t maxlen);
 	void		(*ccid_hc_rx_get_info)(struct sock *sk,
 					       struct tcp_info *info);
 	void		(*ccid_hc_tx_get_info)(struct sock *sk,
@@ -174,6 +177,14 @@ static inline void ccid_hc_tx_packet_sen
 		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
 }
 
+static inline size_t ccid_hc_tx_probe(struct ccid *ccid, struct sock *sk,
+				      char *buf, const size_t maxlen)
+{
+	if (ccid->ccid_ops->ccid_hc_tx_probe != NULL)
+		return ccid->ccid_ops->ccid_hc_tx_probe(sk, buf, maxlen);
+	return 0;
+}
+
 static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
 					  struct sk_buff *skb)
 {
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -362,6 +362,19 @@ static void ccid3_hc_tx_packet_sent(stru
 		DCCP_CRIT("packet history - out of memory!");
 }
 
+static size_t ccid3_hc_tx_probe(struct sock *sk, char *buf, const size_t maxlen)
+{
+	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
+
+	/* Specific field numbering:
+			5   6     7   8        9        10   11
+			s   rtt   p   X_calc   X_recv   X    t_ipi  */
+	return snprintf(buf, maxlen, " %d %d %d %u %u %u %d",
+			hctx->s, hctx->rtt, hctx->p, hctx->x_calc,
+			(unsigned)(hctx->x_recv >> 6),
+			(unsigned)(hctx->x >> 6), hctx->t_ipi);
+}
+
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
 {
 	struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
@@ -848,6 +861,7 @@ struct ccid_operations ccid3_ops = {
 	.ccid_hc_tx_exit	   = ccid3_hc_tx_exit,
 	.ccid_hc_tx_send_packet	   = ccid3_hc_tx_send_packet,
 	.ccid_hc_tx_packet_sent	   = ccid3_hc_tx_packet_sent,
+	.ccid_hc_tx_probe	   = ccid3_hc_tx_probe,
 	.ccid_hc_tx_packet_recv	   = ccid3_hc_tx_packet_recv,
 	.ccid_hc_tx_parse_options  = ccid3_hc_tx_parse_options,
 	.ccid_hc_rx_obj_size	   = sizeof(struct ccid3_hc_rx_sock),
--- a/net/dccp/probe.c
+++ b/net/dccp/probe.c
@@ -34,7 +34,6 @@
 
 #include "dccp.h"
 #include "ccid.h"
-#include "ccids/ccid3.h"
 
 static int port;
 
@@ -52,30 +51,26 @@ static struct {
 static void jdccp_write_xmit(struct sock *sk)
 {
 	const struct inet_sock *inet = inet_sk(sk);
-	struct ccid3_hc_tx_sock *hctx = NULL;
-	struct timespec tv;
-	char buf[256];
-	int len, ccid = ccid_get_current_tx_ccid(dccp_sk(sk));
-
-	if (ccid == DCCPC_CCID3)
-		hctx = ccid3_hc_tx_sk(sk);
 
 	if (!port || ntohs(inet->dport) == port || ntohs(inet->sport) == port) {
-
-		tv  = ktime_to_timespec(ktime_sub(ktime_get(), dccpw.start));
-		len = sprintf(buf, "%lu.%09lu %pI4:%u %pI4:%u %u",
+		char buf[256];
+		struct timespec tv;
+		int len, ccid;
+
+		tv   = ktime_to_timespec(ktime_sub(ktime_get(), dccpw.start));
+		ccid = ccid_get_current_tx_ccid(dccp_sk(sk));
+		/* Basic field numbering (remainder is CCID-dependent):
+				     1         2       3       4
+				     sec.usec  source  dest    ccid */
+		len  = sprintf(buf, "%lu.%09lu %pI4:%u %pI4:%u %u",
 			       (unsigned long)tv.tv_sec,
 			       (unsigned long)tv.tv_nsec,
 			       &inet->saddr, ntohs(inet->sport),
 			       &inet->daddr, ntohs(inet->dport), ccid);
 
-		if (hctx)
-			len += sprintf(buf + len, " %d %d %d %u %u %u %d",
-			       hctx->s, hctx->rtt, hctx->p, hctx->x_calc,
-			       (unsigned)(hctx->x_recv >> 6),
-			       (unsigned)(hctx->x >> 6), hctx->t_ipi);
-
+		len += dccp_xmit_probe(sk, buf + len, sizeof(buf) - len - 1);
 		len += sprintf(buf + len, "\n");
+
 		kfifo_put(dccpw.fifo, buf, len);
 		wake_up(&dccpw.wait);
 	}
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -235,6 +235,7 @@ extern void dccp_send_sync(struct sock *
 			   const enum dccp_pkt_type pkt_type);
 
 extern void   dccp_write_xmit(struct sock *sk);
+extern size_t dccp_xmit_probe(struct sock *sk, char *buf, const size_t maxlen);
 extern void   dccp_write_space(struct sock *sk);
 extern void   dccp_flush_write_queue(struct sock *sk, long *time_budget);
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -365,6 +365,14 @@ void dccp_write_xmit(struct sock *sk)
 	}
 }
 
+size_t dccp_xmit_probe(struct sock *sk, char *buf, const size_t maxlen)
+{
+	struct ccid *tx_ccid = dccp_sk(sk)->dccps_hc_tx_ccid;
+
+	return tx_ccid == NULL ? 0 : ccid_hc_tx_probe(tx_ccid, sk, buf, maxlen);
+}
+EXPORT_SYMBOL_GPL(dccp_xmit_probe);
+
 /**
  * dccp_retransmit_skb  -  Retransmit Request, Close, or CloseReq packets
  * There are only four retransmittable packet types in DCCP:
